Scippy

SCIP

Solving Constraint Integer Programs

var.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 var.c
17  * @brief methods for problem variables
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Marc Pfetsch
23  * @author Michael Winkler
24  * @author Kati Wolter
25  * @author Stefan Vigerske
26  *
27  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
28  * corresponding linear constraint if it exists. This seems to require some work, since the linear
29  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
30  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
31  * changed. This has to be done with care in order to not loose the performance gains of
32  * multi-aggregation.
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "scip/def.h"
42 #include "scip/prop.h"
43 #include "scip/relax.h"
44 #include "scip/var.h"
45 #include "scip/cons.h"
46 #include "scip/event.h"
47 #include "scip/history.h"
48 #include "scip/implics.h"
49 #include "scip/lp.h"
50 #include "scip/primal.h"
51 #include "scip/prob.h"
52 #include "scip/set.h"
53 #include "scip/sol.h"
54 #include "scip/stat.h"
55 #include "scip/tree.h"
56 #include "scip/reopt.h"
57 
58 #include "scip/debug.h"
59 
60 #include "scip/pub_message.h"
61 #include "scip/pub_history.h"
62 
63 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
64  * in implication graph */
65 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
66 
67 /*
68  * hole, holelist, and domain methods
69  */
70 
71 /** creates a new holelist element */
72 static
74  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
75  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
76  SCIP_SET* set, /**< global SCIP settings */
77  SCIP_Real left, /**< left bound of open interval in new hole */
78  SCIP_Real right /**< right bound of open interval in new hole */
79  )
80 {
81  assert(holelist != NULL);
82  assert(blkmem != NULL);
83  assert(SCIPsetIsLT(set, left, right));
84 
85  SCIPdebugMessage("create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
86 
87  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
88  (*holelist)->hole.left = left;
89  (*holelist)->hole.right = right;
90  (*holelist)->next = NULL;
91 
92  return SCIP_OKAY;
93 }
94 
95 /** frees all elements in the holelist */
96 static
97 void holelistFree(
98  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
99  BMS_BLKMEM* blkmem /**< block memory for target holelist */
100  )
101 {
102  assert(holelist != NULL);
103  assert(blkmem != NULL);
104 
105  while( *holelist != NULL )
106  {
107  SCIP_HOLELIST* next;
108 
109  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
110  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
111 
112  next = (*holelist)->next;
113  BMSfreeBlockMemory(blkmem, holelist);
114  assert(*holelist == NULL);
115 
116  *holelist = next;
117  }
118  assert(*holelist == NULL);
119 }
120 
121 /** duplicates a list of holes */
122 static
124  SCIP_HOLELIST** target, /**< pointer to target holelist */
125  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
126  SCIP_SET* set, /**< global SCIP settings */
127  SCIP_HOLELIST* source /**< holelist to duplicate */
128  )
129 {
130  assert(target != NULL);
131 
132  while( source != NULL )
133  {
134  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
135  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
136  source = source->next;
137  target = &(*target)->next;
138  }
139 
140  return SCIP_OKAY;
141 }
142 
143 /** adds a hole to the domain */
144 static
146  SCIP_DOM* dom, /**< domain to add hole to */
147  BMS_BLKMEM* blkmem, /**< block memory */
148  SCIP_SET* set, /**< global SCIP settings */
149  SCIP_Real left, /**< left bound of open interval in new hole */
150  SCIP_Real right, /**< right bound of open interval in new hole */
151  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
152  )
153 {
154  SCIP_HOLELIST** insertpos;
155  SCIP_HOLELIST* next;
156 
157  assert(dom != NULL);
158  assert(added != NULL);
159 
160  /* search for the position of the new hole */
161  insertpos = &dom->holelist;
162  while( *insertpos != NULL && (*insertpos)->hole.left < left )
163  insertpos = &(*insertpos)->next;
164 
165  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
166  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
167  {
168  SCIPdebugMessage("new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
169  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
170  *added = FALSE;
171  return SCIP_OKAY;
172  }
173 
174  /* add hole */
175  *added = TRUE;
176 
177  next = *insertpos;
178  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
179  (*insertpos)->next = next;
180 
181  return SCIP_OKAY;
182 }
183 
184 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
185 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
186  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
187  * merge */
188 static
189 void domMerge(
190  SCIP_DOM* dom, /**< domain to merge */
191  BMS_BLKMEM* blkmem, /**< block memory */
192  SCIP_SET* set, /**< global SCIP settings */
193  SCIP_Real* newlb, /**< pointer to store new lower bound */
194  SCIP_Real* newub /**< pointer to store new upper bound */
195  )
196 {
197  SCIP_HOLELIST** holelistptr;
198  SCIP_HOLELIST** lastnextptr;
199  SCIP_Real* lastrightptr;
200 
201  assert(dom != NULL);
202  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
203 
204 #ifndef NDEBUG
205  {
206  /* check if the holelist is sorted w.r.t. to the left interval bounds */
207  SCIP_Real lastleft;
208 
209  holelistptr = &dom->holelist;
210 
211  lastleft = -SCIPsetInfinity(set);
212 
213  while( *holelistptr != NULL )
214  {
215  if( (*holelistptr)->next != NULL )
216  {
217  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
218  lastleft = (*holelistptr)->hole.left;
219  }
220 
221  holelistptr = &(*holelistptr)->next;
222  }
223  }
224 #endif
225 
226  SCIPdebugMessage("merge hole list\n");
227 
228  holelistptr = &dom->holelist;
229  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
230  lastnextptr = holelistptr;
231 
232  while( *holelistptr != NULL )
233  {
234  SCIPdebugMessage("check hole (%.15g,%.15g) last right interval was <%.15g>\n",
235  (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
236 
237  /* check that the hole is not empty */
238  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
239 
240  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
241  {
242  /* the remaining holes start behind the upper bound: remove them */
243  SCIPdebugMessage("remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
244  holelistFree(holelistptr, blkmem);
245  assert(*holelistptr == NULL);
246 
247  /* unlink this hole from the previous hole */
248  *lastnextptr = NULL;
249  }
250  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
251  {
252  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
253  SCIPdebugMessage("upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
254 
255  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
256 
257  /* adjust upper bound */
258  dom->ub = (*holelistptr)->hole.left;
259 
260  if(newub != NULL )
261  *newub = (*holelistptr)->hole.left;
262 
263  /* remove remaining hole list */
264  holelistFree(holelistptr, blkmem);
265  assert(*holelistptr == NULL);
266 
267  /* unlink this hole from the previous hole */
268  *lastnextptr = NULL;
269  }
270  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
271  {
272  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
273  * the last hole, delete this hole */
274  SCIP_HOLELIST* nextholelist;
275 
276  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
277  {
278  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
279  * the lower bound */
280  SCIPdebugMessage("lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
281  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
282 
283  /* adjust lower bound */
284  dom->lb = *lastrightptr;
285 
286  if(newlb != NULL )
287  *newlb = *lastrightptr;
288  }
289  else
290  {
291  SCIPdebugMessage("current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
292  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
293  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
294  }
295  nextholelist = (*holelistptr)->next;
296  (*holelistptr)->next = NULL;
297  holelistFree(holelistptr, blkmem);
298 
299  /* connect the linked list after removing the hole */
300  *lastnextptr = nextholelist;
301 
302  /* get next hole */
303  *holelistptr = nextholelist;
304  }
305  else
306  {
307  /* the holes do not overlap: update lastholelist and lastrightptr */
308  lastrightptr = &(*holelistptr)->hole.right;
309  lastnextptr = &(*holelistptr)->next;
310 
311  /* get next hole */
312  holelistptr = &(*holelistptr)->next;
313  }
314  }
315 
316 #ifndef NDEBUG
317  {
318  /* check that holes are merged */
319  SCIP_Real lastright;
320 
321  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
322  holelistptr = &dom->holelist;
323 
324  while( *holelistptr != NULL )
325  {
326  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
327  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
328 
329  /* check the hole property (check that the hole is not empty) */
330  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
331  lastright = (*holelistptr)->hole.right;
332 
333  /* get next hole */
334  holelistptr = &(*holelistptr)->next;
335  }
336 
337  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
338  assert( SCIPsetIsLE(set, lastright, dom->ub) );
339  }
340 #endif
341 }
342 
343 /*
344  * domain change methods
345  */
346 
347 /** ensures, that bound change info array for lower bound changes can store at least num entries */
348 static
350  SCIP_VAR* var, /**< problem variable */
351  BMS_BLKMEM* blkmem, /**< block memory */
352  SCIP_SET* set, /**< global SCIP settings */
353  int num /**< minimum number of entries to store */
354  )
355 {
356  assert(var != NULL);
357  assert(var->nlbchginfos <= var->lbchginfossize);
358  assert(SCIPvarIsTransformed(var));
359 
360  if( num > var->lbchginfossize )
361  {
362  int newsize;
363 
364  newsize = SCIPsetCalcMemGrowSize(set, num);
365  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
366  var->lbchginfossize = newsize;
367  }
368  assert(num <= var->lbchginfossize);
369 
370  return SCIP_OKAY;
371 }
372 
373 /** ensures, that bound change info array for upper bound changes can store at least num entries */
374 static
376  SCIP_VAR* var, /**< problem variable */
377  BMS_BLKMEM* blkmem, /**< block memory */
378  SCIP_SET* set, /**< global SCIP settings */
379  int num /**< minimum number of entries to store */
380  )
381 {
382  assert(var != NULL);
383  assert(var->nubchginfos <= var->ubchginfossize);
384  assert(SCIPvarIsTransformed(var));
385 
386  if( num > var->ubchginfossize )
387  {
388  int newsize;
389 
390  newsize = SCIPsetCalcMemGrowSize(set, num);
391  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
392  var->ubchginfossize = newsize;
393  }
394  assert(num <= var->ubchginfossize);
395 
396  return SCIP_OKAY;
397 }
398 
399 /** adds domain change info to the variable's lower bound change info array */
400 static
402  SCIP_VAR* var, /**< problem variable */
403  BMS_BLKMEM* blkmem, /**< block memory */
404  SCIP_SET* set, /**< global SCIP settings */
405  SCIP_Real oldbound, /**< old value for bound */
406  SCIP_Real newbound, /**< new value for bound */
407  int depth, /**< depth in the tree, where the bound change takes place */
408  int pos, /**< position of the bound change in its bound change array */
409  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
410  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
411  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
412  int inferinfo, /**< user information for inference to help resolving the conflict */
413  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
414  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
415  )
416 {
417  assert(var != NULL);
418  assert(SCIPsetIsLT(set, oldbound, newbound));
419  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
420  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
421  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
422  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
423  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
424  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
425  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
426 
427  SCIPdebugMessage("adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
428  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos,
429  infercons != NULL ? "cons" : "prop",
430  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
431  oldbound, newbound);
432 
433  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
434  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
435  var->lbchginfos[var->nlbchginfos].newbound = newbound;
436  var->lbchginfos[var->nlbchginfos].var = var;
437  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
438  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
439  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
440  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
441  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
442  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
443  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
444  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
445  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
446 
447  /**@note The "pos" data member of the bound change info has a size of 27 bits */
448  assert(var->nlbchginfos < 1 << 27);
449 
450  switch( boundchgtype )
451  {
453  break;
455  assert(infercons != NULL);
456  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
457  break;
459  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
460  break;
461  default:
462  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
463  return SCIP_INVALIDDATA;
464  }
465 
466  var->nlbchginfos++;
467 
468  assert(var->nlbchginfos < 2
470  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
471 
472  return SCIP_OKAY;
473 }
474 
475 /** adds domain change info to the variable's upper bound change info array */
476 static
478  SCIP_VAR* var, /**< problem variable */
479  BMS_BLKMEM* blkmem, /**< block memory */
480  SCIP_SET* set, /**< global SCIP settings */
481  SCIP_Real oldbound, /**< old value for bound */
482  SCIP_Real newbound, /**< new value for bound */
483  int depth, /**< depth in the tree, where the bound change takes place */
484  int pos, /**< position of the bound change in its bound change array */
485  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
486  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
487  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
488  int inferinfo, /**< user information for inference to help resolving the conflict */
489  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
490  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
491  )
492 {
493  assert(var != NULL);
494  assert(SCIPsetIsGT(set, oldbound, newbound));
495  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
496  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
497  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
498  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
499  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
500  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
501  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
502 
503  SCIPdebugMessage("adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
504  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos,
505  infercons != NULL ? "cons" : "prop",
506  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
507  oldbound, newbound);
508 
509  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
510  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
511  var->ubchginfos[var->nubchginfos].newbound = newbound;
512  var->ubchginfos[var->nubchginfos].var = var;
513  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
514  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
515  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
516  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
517  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
518  var->ubchginfos[var->nubchginfos].redundant = FALSE;
519  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
520  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
521  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
522 
523  /**@note The "pos" data member of the bound change info has a size of 27 bits */
524  assert(var->nubchginfos < 1 << 27);
525 
526  switch( boundchgtype )
527  {
529  break;
531  assert(infercons != NULL);
532  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
533  break;
535  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
536  break;
537  default:
538  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
539  return SCIP_INVALIDDATA;
540  }
541 
542  var->nubchginfos++;
543 
544  assert(var->nubchginfos < 2
546  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
547 
548  return SCIP_OKAY;
549 }
550 
551 /** applies single bound change */
553  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
554  BMS_BLKMEM* blkmem, /**< block memory */
555  SCIP_SET* set, /**< global SCIP settings */
556  SCIP_STAT* stat, /**< problem statistics */
557  SCIP_LP* lp, /**< current LP data */
558  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
559  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
560  int depth, /**< depth in the tree, where the bound change takes place */
561  int pos, /**< position of the bound change in its bound change array */
562  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
563  )
564 {
565  SCIP_VAR* var;
566 
567  assert(boundchg != NULL);
568  assert(stat != NULL);
569  assert(depth > 0);
570  assert(pos >= 0);
571  assert(cutoff != NULL);
572 
573  *cutoff = FALSE;
574 
575  /* ignore redundant bound changes */
576  if( boundchg->redundant )
577  return SCIP_OKAY;
578 
579  var = boundchg->var;
580  assert(var != NULL);
582  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
583 
584  /* apply bound change */
585  switch( boundchg->boundtype )
586  {
588  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
589  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
590  {
591  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
592  {
593  /* add the bound change info to the variable's bound change info array */
594  switch( boundchg->boundchgtype )
595  {
597  SCIPdebugMessage(" -> branching: new lower bound of <%s>[%g,%g]: %g\n",
598  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
599  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
601  stat->lastbranchvar = var;
603  stat->lastbranchvalue = boundchg->newbound;
604  break;
605 
607  assert(boundchg->data.inferencedata.reason.cons != NULL);
608  SCIPdebugMessage(" -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
609  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
610  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
611  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
612  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
613  boundchg->data.inferencedata.info,
615  break;
616 
618  SCIPdebugMessage(" -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
619  boundchg->data.inferencedata.reason.prop != NULL
620  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
621  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
622  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
623  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
624  boundchg->data.inferencedata.info,
626  break;
627 
628  default:
629  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
630  return SCIP_INVALIDDATA;
631  }
632 
633  /* change local bound of variable */
634  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
635  }
636  else
637  {
638  SCIPdebugMessage(" -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
639  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
640  *cutoff = TRUE;
641  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
642  }
643  }
644  else
645  {
646  /* mark bound change to be inactive */
647  SCIPdebugMessage(" -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
648  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
649  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
650  boundchg->redundant = TRUE;
651  }
652  break;
653 
655  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
656  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
657  {
658  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
659  {
660  /* add the bound change info to the variable's bound change info array */
661  switch( boundchg->boundchgtype )
662  {
664  SCIPdebugMessage(" -> branching: new upper bound of <%s>[%g,%g]: %g\n",
665  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
666  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
668  stat->lastbranchvar = var;
670  stat->lastbranchvalue = boundchg->newbound;
671  break;
672 
674  assert(boundchg->data.inferencedata.reason.cons != NULL);
675  SCIPdebugMessage(" -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
676  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
677  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
678  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
679  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
680  boundchg->data.inferencedata.info,
682  break;
683 
685  SCIPdebugMessage(" -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
686  boundchg->data.inferencedata.reason.prop != NULL
687  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
688  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
689  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
690  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
691  boundchg->data.inferencedata.info,
693  break;
694 
695  default:
696  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
697  return SCIP_INVALIDDATA;
698  }
699 
700  /* change local bound of variable */
701  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
702  }
703  else
704  {
705  SCIPdebugMessage(" -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
706  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
707  *cutoff = TRUE;
708  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
709  }
710  }
711  else
712  {
713  /* mark bound change to be inactive */
714  SCIPdebugMessage(" -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
715  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
716  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
717  boundchg->redundant = TRUE;
718  }
719  break;
720 
721  default:
722  SCIPerrorMessage("unknown bound type\n");
723  return SCIP_INVALIDDATA;
724  }
725 
726  /* update the branching and inference history */
727  if( !boundchg->applied && !boundchg->redundant )
728  {
729  assert(var == boundchg->var);
730 
732  {
733  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
736  }
737  else if( stat->lastbranchvar != NULL )
738  {
739  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
740  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
741  }
742  boundchg->applied = TRUE;
743  }
744 
745  return SCIP_OKAY;
746 }
747 
748 /** undoes single bound change */
750  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
751  BMS_BLKMEM* blkmem, /**< block memory */
752  SCIP_SET* set, /**< global SCIP settings */
753  SCIP_STAT* stat, /**< problem statistics */
754  SCIP_LP* lp, /**< current LP data */
755  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
756  SCIP_EVENTQUEUE* eventqueue /**< event queue */
757  )
758 {
759  SCIP_VAR* var;
760 
761  assert(boundchg != NULL);
762  assert(stat != NULL);
763 
764  /* ignore redundant bound changes */
765  if( boundchg->redundant )
766  return SCIP_OKAY;
767 
768  var = boundchg->var;
769  assert(var != NULL);
771 
772  /* undo bound change: apply the previous bound change of variable */
773  switch( boundchg->boundtype )
774  {
776  var->nlbchginfos--;
777  assert(var->nlbchginfos >= 0);
778  assert(var->lbchginfos != NULL);
779  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
780  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
781 
782  SCIPdebugMessage("removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
783  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
786 
787  /* reinstall the previous local bound */
788  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
789  var->lbchginfos[var->nlbchginfos].oldbound) );
790 
791  /* in case all bound changes are removed the local bound should match the global bound */
792  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
793 
794  break;
795 
797  var->nubchginfos--;
798  assert(var->nubchginfos >= 0);
799  assert(var->ubchginfos != NULL);
800  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
801  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
802 
803  SCIPdebugMessage("removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
804  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
807 
808  /* reinstall the previous local bound */
809  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
810  var->ubchginfos[var->nubchginfos].oldbound) );
811 
812  /* in case all bound changes are removed the local bound should match the global bound */
813  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
814 
815  break;
816 
817  default:
818  SCIPerrorMessage("unknown bound type\n");
819  return SCIP_INVALIDDATA;
820  }
821 
822  /* update last branching variable */
824  {
825  stat->lastbranchvar = NULL;
827  }
828 
829  return SCIP_OKAY;
830 }
831 
832 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
833 static
835  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
836  BMS_BLKMEM* blkmem, /**< block memory */
837  SCIP_SET* set, /**< global SCIP settings */
838  SCIP_STAT* stat, /**< problem statistics */
839  SCIP_LP* lp, /**< current LP data */
840  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
841  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
842  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
843  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
844  )
845 {
846  SCIP_VAR* var;
847  SCIP_Real newbound;
848  SCIP_BOUNDTYPE boundtype;
849 
850  assert(boundchg != NULL);
851  assert(cutoff != NULL);
852 
853  *cutoff = FALSE;
854 
855  /* ignore redundant bound changes */
856  if( boundchg->redundant )
857  return SCIP_OKAY;
858 
859  var = SCIPboundchgGetVar(boundchg);
860  newbound = SCIPboundchgGetNewbound(boundchg);
861  boundtype = SCIPboundchgGetBoundtype(boundchg);
862 
863  /* check if the bound change is redundant which can happen due to a (better) global bound change which was perforemed
864  * after that bound change was applied
865  *
866  * @note a global bound change is not captured by the redundant member of the bound change data structure
867  */
868  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
869  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
870  {
871  return SCIP_OKAY;
872  }
873 
874  SCIPdebugMessage("applying global bound change: <%s>[%g,%g] %s %g\n",
876  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
877 
878  /* check for cutoff */
879  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
880  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
881  {
882  *cutoff = TRUE;
883  return SCIP_OKAY;
884  }
885 
886  /* apply bound change */
887  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
888 
889  return SCIP_OKAY;
890 }
891 
892 /** captures branching and inference data of bound change */
893 static
895  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
896  )
897 {
898  assert(boundchg != NULL);
899 
900  /* capture variable associated with the bound change */
901  assert(boundchg->var != NULL);
902  SCIPvarCapture(boundchg->var);
903 
904  switch( boundchg->boundchgtype )
905  {
908  break;
909 
911  assert(boundchg->data.inferencedata.var != NULL);
912  assert(boundchg->data.inferencedata.reason.cons != NULL);
913  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
914  break;
915 
916  default:
917  SCIPerrorMessage("invalid bound change type\n");
918  return SCIP_INVALIDDATA;
919  }
920 
921  return SCIP_OKAY;
922 }
923 
924 /** releases branching and inference data of bound change */
925 static
927  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
928  BMS_BLKMEM* blkmem, /**< block memory */
929  SCIP_SET* set, /**< global SCIP settings */
930  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
931  SCIP_LP* lp /**< current LP data */
932 
933  )
934 {
935  assert(boundchg != NULL);
936 
937  switch( boundchg->boundchgtype )
938  {
941  break;
942 
944  assert(boundchg->data.inferencedata.var != NULL);
945  assert(boundchg->data.inferencedata.reason.cons != NULL);
946  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
947  break;
948 
949  default:
950  SCIPerrorMessage("invalid bound change type\n");
951  return SCIP_INVALIDDATA;
952  }
953 
954  /* release variable */
955  assert(boundchg->var != NULL);
956  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
957 
958 
959  return SCIP_OKAY;
960 }
961 
962 /** creates empty domain change data with dynamic arrays */
963 static
965  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
966  BMS_BLKMEM* blkmem /**< block memory */
967  )
968 {
969  assert(domchg != NULL);
970  assert(blkmem != NULL);
971 
972  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
973  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
974  (*domchg)->domchgdyn.nboundchgs = 0;
975  (*domchg)->domchgdyn.boundchgs = NULL;
976  (*domchg)->domchgdyn.nholechgs = 0;
977  (*domchg)->domchgdyn.holechgs = NULL;
978  (*domchg)->domchgdyn.boundchgssize = 0;
979  (*domchg)->domchgdyn.holechgssize = 0;
980 
981  return SCIP_OKAY;
982 }
983 
984 /** frees domain change data */
986  SCIP_DOMCHG** domchg, /**< pointer to domain change */
987  BMS_BLKMEM* blkmem, /**< block memory */
988  SCIP_SET* set, /**< global SCIP settings */
989  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
990  SCIP_LP* lp /**< current LP data */
991  )
992 {
993  assert(domchg != NULL);
994  assert(blkmem != NULL);
995 
996  if( *domchg != NULL )
997  {
998  int i;
999 
1000  /* release variables, branching and inference data associated with the bound changes */
1001  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1002  {
1003  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1004  }
1005 
1006  /* free memory for bound and hole changes */
1007  switch( (*domchg)->domchgdyn.domchgtype )
1008  {
1009  case SCIP_DOMCHGTYPE_BOUND:
1010  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1011  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1012  break;
1013  case SCIP_DOMCHGTYPE_BOTH:
1014  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1015  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1016  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1017  break;
1019  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1020  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1021  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1022  break;
1023  default:
1024  SCIPerrorMessage("invalid domain change type\n");
1025  return SCIP_INVALIDDATA;
1026  }
1027  }
1028 
1029  return SCIP_OKAY;
1030 }
1031 
1032 /** converts a static domain change data into a dynamic one */
1033 static
1035  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1036  BMS_BLKMEM* blkmem /**< block memory */
1037  )
1038 {
1039  assert(domchg != NULL);
1040  assert(blkmem != NULL);
1041 
1042  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1043 
1044  if( *domchg == NULL )
1045  {
1046  SCIP_CALL( domchgCreate(domchg, blkmem) );
1047  }
1048  else
1049  {
1050  switch( (*domchg)->domchgdyn.domchgtype )
1051  {
1052  case SCIP_DOMCHGTYPE_BOUND:
1053  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1054  (*domchg)->domchgdyn.nholechgs = 0;
1055  (*domchg)->domchgdyn.holechgs = NULL;
1056  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1057  (*domchg)->domchgdyn.holechgssize = 0;
1058  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1059  break;
1060  case SCIP_DOMCHGTYPE_BOTH:
1061  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1062  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1063  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1064  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1065  break;
1067  break;
1068  default:
1069  SCIPerrorMessage("invalid domain change type\n");
1070  return SCIP_INVALIDDATA;
1071  }
1072  }
1073 #ifndef NDEBUG
1074  {
1075  int i;
1076  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1078  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1079  }
1080 #endif
1081 
1082  return SCIP_OKAY;
1083 }
1084 
1085 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1087  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1088  BMS_BLKMEM* blkmem, /**< block memory */
1089  SCIP_SET* set, /**< global SCIP settings */
1090  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1091  SCIP_LP* lp /**< current LP data */
1092  )
1093 {
1094  assert(domchg != NULL);
1095  assert(blkmem != NULL);
1096 
1097  SCIPdebugMessage("making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1098 
1099  if( *domchg != NULL )
1100  {
1101  switch( (*domchg)->domchgdyn.domchgtype )
1102  {
1103  case SCIP_DOMCHGTYPE_BOUND:
1104  if( (*domchg)->domchgbound.nboundchgs == 0 )
1105  {
1106  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1107  }
1108  break;
1109  case SCIP_DOMCHGTYPE_BOTH:
1110  if( (*domchg)->domchgboth.nholechgs == 0 )
1111  {
1112  if( (*domchg)->domchgbound.nboundchgs == 0 )
1113  {
1114  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1115  }
1116  else
1117  {
1118  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1119  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1120  }
1121  }
1122  break;
1124  if( (*domchg)->domchgboth.nholechgs == 0 )
1125  {
1126  if( (*domchg)->domchgbound.nboundchgs == 0 )
1127  {
1128  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1129  }
1130  else
1131  {
1132  /* shrink dynamic size arrays to their minimal sizes */
1133  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1134  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1135  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1136 
1137  /* convert into static domain change */
1138  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1139  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1140  }
1141  }
1142  else
1143  {
1144  /* shrink dynamic size arrays to their minimal sizes */
1145  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1146  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1147  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs,
1148  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1149 
1150  /* convert into static domain change */
1151  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1152  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1153  }
1154  break;
1155  default:
1156  SCIPerrorMessage("invalid domain change type\n");
1157  return SCIP_INVALIDDATA;
1158  }
1159 #ifndef NDEBUG
1160  if( *domchg != NULL )
1161  {
1162  int i;
1163  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1164  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1165  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1166  }
1167 #endif
1168  }
1169 
1170  return SCIP_OKAY;
1171 }
1172 
1173 /** ensures, that boundchgs array can store at least num entries */
1174 static
1176  SCIP_DOMCHG* domchg, /**< domain change data structure */
1177  BMS_BLKMEM* blkmem, /**< block memory */
1178  SCIP_SET* set, /**< global SCIP settings */
1179  int num /**< minimum number of entries to store */
1180  )
1181 {
1182  assert(domchg != NULL);
1183  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1184 
1185  if( num > domchg->domchgdyn.boundchgssize )
1186  {
1187  int newsize;
1188 
1189  newsize = SCIPsetCalcMemGrowSize(set, num);
1190  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1191  domchg->domchgdyn.boundchgssize = newsize;
1192  }
1193  assert(num <= domchg->domchgdyn.boundchgssize);
1194 
1195  return SCIP_OKAY;
1196 }
1197 
1198 /** ensures, that holechgs array can store at least num additional entries */
1199 static
1201  SCIP_DOMCHG* domchg, /**< domain change data structure */
1202  BMS_BLKMEM* blkmem, /**< block memory */
1203  SCIP_SET* set, /**< global SCIP settings */
1204  int num /**< minimum number of additional entries to store */
1205  )
1206 {
1207  assert(domchg != NULL);
1208  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1209 
1210  if( num > domchg->domchgdyn.holechgssize )
1211  {
1212  int newsize;
1213 
1214  newsize = SCIPsetCalcMemGrowSize(set, num);
1215  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1216  domchg->domchgdyn.holechgssize = newsize;
1217  }
1218  assert(num <= domchg->domchgdyn.holechgssize);
1219 
1220  return SCIP_OKAY;
1221 }
1222 
1223 /** applies domain change */
1225  SCIP_DOMCHG* domchg, /**< domain change to apply */
1226  BMS_BLKMEM* blkmem, /**< block memory */
1227  SCIP_SET* set, /**< global SCIP settings */
1228  SCIP_STAT* stat, /**< problem statistics */
1229  SCIP_LP* lp, /**< current LP data */
1230  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1231  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1232  int depth, /**< depth in the tree, where the domain change takes place */
1233  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1234  )
1235 {
1236  int i;
1237 
1238  assert(cutoff != NULL);
1239 
1240  *cutoff = FALSE;
1241 
1242  SCIPdebugMessage("applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1243 
1244  if( domchg == NULL )
1245  return SCIP_OKAY;
1246 
1247  /* apply bound changes */
1248  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1249  {
1250  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1251  branchcand, eventqueue, depth, i, cutoff) );
1252  if( *cutoff )
1253  break;
1254  }
1255  SCIPdebugMessage(" -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1256 
1257  /* mark all bound changes after a cutoff redundant */
1258  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1259  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1260 
1261  /* apply holelist changes */
1262  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1263  {
1264  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1265  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1266  SCIPdebugMessage(" -> %d hole changes\n", domchg->domchgboth.nholechgs);
1267  }
1268 
1269  return SCIP_OKAY;
1270 }
1271 
1272 /** undoes domain change */
1274  SCIP_DOMCHG* domchg, /**< domain change to remove */
1275  BMS_BLKMEM* blkmem, /**< block memory */
1276  SCIP_SET* set, /**< global SCIP settings */
1277  SCIP_STAT* stat, /**< problem statistics */
1278  SCIP_LP* lp, /**< current LP data */
1279  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1280  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1281  )
1282 {
1283  int i;
1284 
1285  SCIPdebugMessage("undoing domain changes at %p\n", (void*)domchg);
1286  if( domchg == NULL )
1287  return SCIP_OKAY;
1288 
1289  /* undo holelist changes */
1290  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1291  {
1292  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1293  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1294  SCIPdebugMessage(" -> %d hole changes\n", domchg->domchgboth.nholechgs);
1295  }
1296 
1297  /* undo bound changes */
1298  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1299  {
1300  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1301  }
1302  SCIPdebugMessage(" -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1303 
1304  return SCIP_OKAY;
1305 }
1306 
1307 /** applies domain change to the global problem */
1309  SCIP_DOMCHG* domchg, /**< domain change to apply */
1310  BMS_BLKMEM* blkmem, /**< block memory */
1311  SCIP_SET* set, /**< global SCIP settings */
1312  SCIP_STAT* stat, /**< problem statistics */
1313  SCIP_LP* lp, /**< current LP data */
1314  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1315  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1316  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1317  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1318  )
1319 {
1320  int i;
1321 
1322  assert(cutoff != NULL);
1323 
1324  *cutoff = FALSE;
1325 
1326  if( domchg == NULL )
1327  return SCIP_OKAY;
1328 
1329  SCIPdebugMessage("applying domain changes at %p to the global problem\n", (void*)domchg);
1330 
1331  /* apply bound changes */
1332  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1333  {
1334  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1335  branchcand, eventqueue, cliquetable, cutoff) );
1336  if( *cutoff )
1337  break;
1338  }
1339  SCIPdebugMessage(" -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1340 
1341  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1342 
1343  return SCIP_OKAY;
1344 }
1345 
1346 /** adds bound change to domain changes */
1348  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1349  BMS_BLKMEM* blkmem, /**< block memory */
1350  SCIP_SET* set, /**< global SCIP settings */
1351  SCIP_VAR* var, /**< variable to change the bounds for */
1352  SCIP_Real newbound, /**< new value for bound */
1353  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1354  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1355  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1356  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1357  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1358  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1359  int inferinfo, /**< user information for inference to help resolving the conflict */
1360  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1361  )
1362 {
1363  SCIP_BOUNDCHG* boundchg;
1364 
1365  assert(domchg != NULL);
1366  assert(var != NULL);
1368  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1369  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1370  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1371  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1372  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1373 
1374  SCIPdebugMessage("adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1375  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper",
1376  boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1377  newbound, var->name, (void*)domchg, (void*)*domchg);
1378 
1379  /* if domain change data doesn't exist, create it;
1380  * if domain change is static, convert it into dynamic change
1381  */
1382  if( *domchg == NULL )
1383  {
1384  SCIP_CALL( domchgCreate(domchg, blkmem) );
1385  }
1386  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1387  {
1388  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1389  }
1390  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1391 
1392  /* get memory for additional bound change */
1393  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1394 
1395  /* fill in the bound change data */
1396  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1397  boundchg->var = var;
1398  switch( boundchgtype )
1399  {
1401  boundchg->data.branchingdata.lpsolval = lpsolval;
1402  break;
1404  assert(infercons != NULL);
1405  boundchg->data.inferencedata.var = infervar;
1406  boundchg->data.inferencedata.reason.cons = infercons;
1407  boundchg->data.inferencedata.info = inferinfo;
1408  break;
1410  boundchg->data.inferencedata.var = infervar;
1411  boundchg->data.inferencedata.reason.prop = inferprop;
1412  boundchg->data.inferencedata.info = inferinfo;
1413  break;
1414  default:
1415  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1416  return SCIP_INVALIDDATA;
1417  }
1418 
1419  boundchg->newbound = newbound;
1420  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1421  boundchg->boundtype = boundtype; /*lint !e641*/
1422  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1423  boundchg->applied = FALSE;
1424  boundchg->redundant = FALSE;
1425  (*domchg)->domchgdyn.nboundchgs++;
1426 
1427  /* capture branching and inference data associated with the bound changes */
1428  SCIP_CALL( boundchgCaptureData(boundchg) );
1429 
1430 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1431 #ifdef SCIP_MORE_DEBUG
1432  {
1433  int i;
1434  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1435  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1436  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1437  }
1438 #endif
1439 #endif
1440 
1441  return SCIP_OKAY;
1442 }
1443 
1444 /** adds hole change to domain changes */
1446  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1447  BMS_BLKMEM* blkmem, /**< block memory */
1448  SCIP_SET* set, /**< global SCIP settings */
1449  SCIP_HOLELIST** ptr, /**< changed list pointer */
1450  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1451  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1452  )
1453 {
1454  SCIP_HOLECHG* holechg;
1455 
1456  assert(domchg != NULL);
1457  assert(ptr != NULL);
1458 
1459  /* if domain change data doesn't exist, create it;
1460  * if domain change is static, convert it into dynamic change
1461  */
1462  if( *domchg == NULL )
1463  {
1464  SCIP_CALL( domchgCreate(domchg, blkmem) );
1465  }
1466  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1467  {
1468  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1469  }
1470  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1471 
1472  /* get memory for additional hole change */
1473  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1474 
1475  /* fill in the hole change data */
1476  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1477  holechg->ptr = ptr;
1478  holechg->newlist = newlist;
1479  holechg->oldlist = oldlist;
1480  (*domchg)->domchgdyn.nholechgs++;
1481 
1482  return SCIP_OKAY;
1483 }
1484 
1485 
1486 
1487 
1488 /*
1489  * methods for variables
1490  */
1491 
1492 /** returns adjusted lower bound value, which is rounded for integral variable types */
1493 static
1495  SCIP_SET* set, /**< global SCIP settings */
1496  SCIP_VARTYPE vartype, /**< type of variable */
1497  SCIP_Real lb /**< lower bound to adjust */
1498  )
1499 {
1500  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1501  return -SCIPsetInfinity(set);
1502  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1503  return SCIPsetInfinity(set);
1504  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1505  return SCIPsetFeasCeil(set, lb);
1506  else if( SCIPsetIsZero(set, lb) )
1507  return 0.0;
1508  else
1509  return lb;
1510 }
1511 
1512 /** returns adjusted upper bound value, which is rounded for integral variable types */
1513 static
1515  SCIP_SET* set, /**< global SCIP settings */
1516  SCIP_VARTYPE vartype, /**< type of variable */
1517  SCIP_Real ub /**< upper bound to adjust */
1518  )
1519 {
1520  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1521  return SCIPsetInfinity(set);
1522  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1523  return -SCIPsetInfinity(set);
1524  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1525  return SCIPsetFeasFloor(set, ub);
1526  else if( SCIPsetIsZero(set, ub) )
1527  return 0.0;
1528  else
1529  return ub;
1530 }
1531 
1532 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1533  * bounds arrays, and optionally removes them also from the variable itself
1534  */
1536  SCIP_VAR* var, /**< problem variable */
1537  BMS_BLKMEM* blkmem, /**< block memory */
1538  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1539  SCIP_SET* set, /**< global SCIP settings */
1540  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1541  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1542  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1543  )
1544 {
1545  SCIP_Real lb;
1546  SCIP_Real ub;
1547 
1548  assert(var != NULL);
1550  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1551 
1552  lb = SCIPvarGetLbGlobal(var);
1553  ub = SCIPvarGetUbGlobal(var);
1554 
1555  SCIPdebugMessage("removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1556  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1557 
1558  /* remove implications of (fixed) binary variable */
1559  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1560  {
1561  SCIP_Bool varfixing;
1562 
1563  assert(SCIPvarIsBinary(var));
1564 
1565  varfixing = FALSE;
1566  do
1567  {
1568  SCIP_VAR** implvars;
1569  SCIP_BOUNDTYPE* impltypes;
1570  int nimpls;
1571  int i;
1572 
1573  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1574  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1575  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1576 
1577  for( i = 0; i < nimpls; i++ )
1578  {
1579  SCIP_VAR* implvar;
1580  SCIP_BOUNDTYPE impltype;
1581 
1582  implvar = implvars[i];
1583  impltype = impltypes[i];
1584  assert(implvar != var);
1585 
1586  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1587  * the following variable bound from x's variable bounds
1588  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1589  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1590  */
1591  if( impltype == SCIP_BOUNDTYPE_UPPER )
1592  {
1593  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1594  {
1595  SCIPdebugMessage("deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1596  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1597  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1598  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1599  implvar->closestvblpcount = -1;
1600  var->closestvblpcount = -1;
1601  }
1602  }
1603  else
1604  {
1605  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1606  {
1607  SCIPdebugMessage("deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1608  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1609  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1610  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1611  implvar->closestvblpcount = -1;
1612  var->closestvblpcount = -1;
1613  }
1614  }
1615  }
1616  varfixing = !varfixing;
1617  }
1618  while( varfixing == TRUE );
1619 
1620  if( removefromvar )
1621  {
1622  /* free the implications data structures */
1623  SCIPimplicsFree(&var->implics, blkmem);
1624  }
1625  }
1626 
1627  /* remove the (redundant) variable lower bounds */
1628  if( var->vlbs != NULL )
1629  {
1630  SCIP_VAR** vars;
1631  SCIP_Real* coefs;
1632  SCIP_Real* constants;
1633  int nvbds;
1634  int newnvbds;
1635  int i;
1636 
1637  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1638  vars = SCIPvboundsGetVars(var->vlbs);
1639  coefs = SCIPvboundsGetCoefs(var->vlbs);
1640  constants = SCIPvboundsGetConstants(var->vlbs);
1641 
1642  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1643  * z == ub ==> x >= b*ub + d , if b > 0
1644  * z == lb ==> x >= b*lb + d , if b < 0
1645  */
1646  newnvbds = 0;
1647  for( i = 0; i < nvbds; i++ )
1648  {
1649  SCIP_VAR* implvar;
1650  SCIP_Real coef;
1651 
1652  assert(newnvbds <= i);
1653 
1654  implvar = vars[i];
1655  assert(implvar != NULL);
1656 
1657  coef = coefs[i];
1658  assert(!SCIPsetIsZero(set, coef));
1659 
1660  /* check, if we want to remove the variable bound */
1661  if( onlyredundant )
1662  {
1663  SCIP_Real vbound;
1664 
1665  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1666  if( SCIPsetIsFeasGT(set, vbound, lb) )
1667  {
1668  /* the variable bound is not redundant: keep it */
1669  if( removefromvar )
1670  {
1671  if( newnvbds < i )
1672  {
1673  vars[newnvbds] = implvar;
1674  coefs[newnvbds] = coef;
1675  constants[newnvbds] = constants[i];
1676  }
1677  newnvbds++;
1678  }
1679  continue;
1680  }
1681  }
1682 
1683  /* remove the corresponding implication */
1684  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1685  {
1686  SCIPdebugMessage("deleting implication: <%s> == %d ==> <%s> >= %g\n",
1687  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1688  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1689  }
1690  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1691  {
1692  SCIPdebugMessage("deleting variable upper bound from <%s> involving variable %s\n",
1693  SCIPvarGetName(implvar), SCIPvarGetName(var));
1694  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1695  implvar->closestvblpcount = -1;
1696  var->closestvblpcount = -1;
1697  }
1698  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1699  {
1700  SCIPdebugMessage("deleting variable lower bound from <%s> involving variable %s\n",
1701  SCIPvarGetName(implvar), SCIPvarGetName(var));
1702  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1703  implvar->closestvblpcount = -1;
1704  var->closestvblpcount = -1;
1705  }
1706  }
1707 
1708  if( removefromvar )
1709  {
1710  /* update the number of variable bounds */
1711  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1712  var->closestvblpcount = -1;
1713  }
1714  }
1715 
1716  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1717  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1718  * cannot remove such variables x from z's implications.
1719  */
1720 
1721  /* remove the (redundant) variable upper bounds */
1722  if( var->vubs != NULL )
1723  {
1724  SCIP_VAR** vars;
1725  SCIP_Real* coefs;
1726  SCIP_Real* constants;
1727  int nvbds;
1728  int newnvbds;
1729  int i;
1730 
1731  nvbds = SCIPvboundsGetNVbds(var->vubs);
1732  vars = SCIPvboundsGetVars(var->vubs);
1733  coefs = SCIPvboundsGetCoefs(var->vubs);
1734  constants = SCIPvboundsGetConstants(var->vubs);
1735 
1736  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1737  * z == lb ==> x <= b*lb + d , if b > 0
1738  * z == ub ==> x <= b*ub + d , if b < 0
1739  */
1740  newnvbds = 0;
1741  for( i = 0; i < nvbds; i++ )
1742  {
1743  SCIP_VAR* implvar;
1744  SCIP_Real coef;
1745 
1746  assert(newnvbds <= i);
1747 
1748  implvar = vars[i];
1749  assert(implvar != NULL);
1750 
1751  coef = coefs[i];
1752  assert(!SCIPsetIsZero(set, coef));
1753 
1754  /* check, if we want to remove the variable bound */
1755  if( onlyredundant )
1756  {
1757  SCIP_Real vbound;
1758 
1759  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1760  if( SCIPsetIsFeasLT(set, vbound, ub) )
1761  {
1762  /* the variable bound is not redundant: keep it */
1763  if( removefromvar )
1764  {
1765  if( newnvbds < i )
1766  {
1767  vars[newnvbds] = implvar;
1768  coefs[newnvbds] = coefs[i];
1769  constants[newnvbds] = constants[i];
1770  }
1771  newnvbds++;
1772  }
1773  continue;
1774  }
1775  }
1776 
1777  /* remove the corresponding implication */
1778  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1779  {
1780  SCIPdebugMessage("deleting implication: <%s> == %d ==> <%s> <= %g\n",
1781  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1782  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1783  }
1784  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1785  {
1786  SCIPdebugMessage("deleting variable upper bound from <%s> involving variable %s\n",
1787  SCIPvarGetName(implvar), SCIPvarGetName(var));
1788  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1789  implvar->closestvblpcount = -1;
1790  var->closestvblpcount = -1;
1791  }
1792  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1793  {
1794  SCIPdebugMessage("deleting variable lower bound from <%s> involving variable %s\n",
1795  SCIPvarGetName(implvar), SCIPvarGetName(var));
1796  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1797  implvar->closestvblpcount = -1;
1798  var->closestvblpcount = -1;
1799  }
1800  }
1801 
1802  if( removefromvar )
1803  {
1804  /* update the number of variable bounds */
1805  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1806  var->closestvblpcount = -1;
1807  }
1808  }
1809 
1810  /* remove the variable from all cliques */
1811  if( SCIPvarIsBinary(var) )
1812  {
1813  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1814  SCIPcliquelistFree(&var->cliquelist, blkmem);
1815  }
1816 
1817  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1818  * z has no link (like in the binary case) to x
1819  */
1820 
1821  return SCIP_OKAY;
1822 }
1823 
1824 /** sets the variable name */
1825 static
1827  SCIP_VAR* var, /**< problem variable */
1828  BMS_BLKMEM* blkmem, /**< block memory */
1829  SCIP_STAT* stat, /**< problem statistics, or NULL */
1830  const char* name /**< name of variable, or NULL for automatic name creation */
1831  )
1832 {
1833  assert(blkmem != NULL);
1834  assert(var != NULL);
1835 
1836  if( name == NULL )
1837  {
1838  char s[SCIP_MAXSTRLEN];
1839 
1840  assert(stat != NULL);
1841 
1842  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1843  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1844  }
1845  else
1846  {
1847  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1848  }
1849 
1850  return SCIP_OKAY;
1851 }
1852 
1853 
1854 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1855  * with bounds zero and one is automatically converted into a binary variable
1856  */
1857 static
1859  SCIP_VAR** var, /**< pointer to variable data */
1860  BMS_BLKMEM* blkmem, /**< block memory */
1861  SCIP_SET* set, /**< global SCIP settings */
1862  SCIP_STAT* stat, /**< problem statistics */
1863  const char* name, /**< name of variable, or NULL for automatic name creation */
1864  SCIP_Real lb, /**< lower bound of variable */
1865  SCIP_Real ub, /**< upper bound of variable */
1866  SCIP_Real obj, /**< objective function value */
1867  SCIP_VARTYPE vartype, /**< type of variable */
1868  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1869  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1870  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1871  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1872  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1873  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1874  SCIP_VARDATA* vardata /**< user data for this specific variable */
1875  )
1876 {
1877  assert(var != NULL);
1878  assert(blkmem != NULL);
1879  assert(stat != NULL);
1880 
1881  /* adjust bounds of variable */
1882  lb = adjustedLb(set, vartype, lb);
1883  ub = adjustedUb(set, vartype, ub);
1884 
1885  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1886  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1887  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1888  {
1889  if( vartype == SCIP_VARTYPE_INTEGER )
1890  vartype = SCIP_VARTYPE_BINARY;
1891  }
1892  else
1893  {
1894  if( vartype == SCIP_VARTYPE_BINARY )
1895  {
1896  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1897  return SCIP_INVALIDDATA;
1898  }
1899  }
1900 
1901  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1902  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1903 
1904  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1905 
1906  /* set variable's name */
1907  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1908 
1909 #ifndef NDEBUG
1910  (*var)->scip = set->scip;
1911 #endif
1912  (*var)->obj = obj;
1913  (*var)->unchangedobj = obj;
1914  (*var)->branchfactor = 1.0;
1915  (*var)->rootsol = 0.0;
1916  (*var)->bestrootsol = 0.0;
1917  (*var)->bestrootredcost = 0.0;
1918  (*var)->bestrootlpobjval = SCIP_INVALID;
1919  (*var)->relaxsol = 0.0;
1920  (*var)->nlpsol = 0.0;
1921  (*var)->primsolavg = 0.5 * (lb + ub);
1922  (*var)->conflictlb = SCIP_REAL_MIN;
1923  (*var)->conflictub = SCIP_REAL_MAX;
1924  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1925  (*var)->conflictrelaxedub = (*var)->conflictub;
1926  (*var)->lazylb = -SCIPsetInfinity(set);
1927  (*var)->lazyub = SCIPsetInfinity(set);
1928  (*var)->glbdom.holelist = NULL;
1929  (*var)->glbdom.lb = lb;
1930  (*var)->glbdom.ub = ub;
1931  (*var)->locdom.holelist = NULL;
1932  (*var)->locdom.lb = lb;
1933  (*var)->locdom.ub = ub;
1934  (*var)->varcopy = varcopy;
1935  (*var)->vardelorig = vardelorig;
1936  (*var)->vartrans = vartrans;
1937  (*var)->vardeltrans = vardeltrans;
1938  (*var)->vardata = vardata;
1939  (*var)->parentvars = NULL;
1940  (*var)->negatedvar = NULL;
1941  (*var)->vlbs = NULL;
1942  (*var)->vubs = NULL;
1943  (*var)->implics = NULL;
1944  (*var)->cliquelist = NULL;
1945  (*var)->eventfilter = NULL;
1946  (*var)->lbchginfos = NULL;
1947  (*var)->ubchginfos = NULL;
1948  (*var)->index = stat->nvaridx;
1949  (*var)->probindex = -1;
1950  (*var)->pseudocandindex = -1;
1951  (*var)->eventqueueindexobj = -1;
1952  (*var)->eventqueueindexlb = -1;
1953  (*var)->eventqueueindexub = -1;
1954  (*var)->parentvarssize = 0;
1955  (*var)->nparentvars = 0;
1956  (*var)->nuses = 0;
1957  (*var)->nlocksdown = 0;
1958  (*var)->nlocksup = 0;
1959  (*var)->branchpriority = 0;
1960  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1961  (*var)->lbchginfossize = 0;
1962  (*var)->nlbchginfos = 0;
1963  (*var)->ubchginfossize = 0;
1964  (*var)->nubchginfos = 0;
1965  (*var)->conflictlbcount = 0;
1966  (*var)->conflictubcount = 0;
1967  (*var)->closestvlbidx = -1;
1968  (*var)->closestvubidx = -1;
1969  (*var)->closestvblpcount = -1;
1970  (*var)->initial = initial;
1971  (*var)->removable = removable;
1972  (*var)->deleted = FALSE;
1973  (*var)->donotmultaggr = FALSE;
1974  (*var)->vartype = vartype; /*lint !e641*/
1975  (*var)->pseudocostflag = FALSE;
1976  (*var)->eventqueueimpl = FALSE;
1977  (*var)->deletable = FALSE;
1978  (*var)->delglobalstructs = FALSE;
1979 
1980  stat->nvaridx++;
1981 
1982  /* create branching and inference history entries */
1983  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1984  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1985 
1986  /* the value based history is only created on demand */
1987  (*var)->valuehistory = NULL;
1988 
1989  return SCIP_OKAY;
1990 }
1991 
1992 /** creates and captures an original problem variable; an integer variable with bounds
1993  * zero and one is automatically converted into a binary variable
1994  */
1996  SCIP_VAR** var, /**< pointer to variable data */
1997  BMS_BLKMEM* blkmem, /**< block memory */
1998  SCIP_SET* set, /**< global SCIP settings */
1999  SCIP_STAT* stat, /**< problem statistics */
2000  const char* name, /**< name of variable, or NULL for automatic name creation */
2001  SCIP_Real lb, /**< lower bound of variable */
2002  SCIP_Real ub, /**< upper bound of variable */
2003  SCIP_Real obj, /**< objective function value */
2004  SCIP_VARTYPE vartype, /**< type of variable */
2005  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2006  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2007  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2008  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2009  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2010  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2011  SCIP_VARDATA* vardata /**< user data for this specific variable */
2012  )
2013 {
2014  assert(var != NULL);
2015  assert(blkmem != NULL);
2016  assert(stat != NULL);
2017 
2018  /* create variable */
2019  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2020  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2021 
2022  /* set variable status and data */
2023  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2024  (*var)->data.original.origdom.holelist = NULL;
2025  (*var)->data.original.origdom.lb = lb;
2026  (*var)->data.original.origdom.ub = ub;
2027  (*var)->data.original.transvar = NULL;
2028 
2029  /* capture variable */
2030  SCIPvarCapture(*var);
2031 
2032  return SCIP_OKAY;
2033 }
2034 
2035 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2036  * zero and one is automatically converted into a binary variable
2037  */
2039  SCIP_VAR** var, /**< pointer to variable data */
2040  BMS_BLKMEM* blkmem, /**< block memory */
2041  SCIP_SET* set, /**< global SCIP settings */
2042  SCIP_STAT* stat, /**< problem statistics */
2043  const char* name, /**< name of variable, or NULL for automatic name creation */
2044  SCIP_Real lb, /**< lower bound of variable */
2045  SCIP_Real ub, /**< upper bound of variable */
2046  SCIP_Real obj, /**< objective function value */
2047  SCIP_VARTYPE vartype, /**< type of variable */
2048  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2049  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2050  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2051  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2052  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2053  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2054  SCIP_VARDATA* vardata /**< user data for this specific variable */
2055  )
2056 {
2057  assert(var != NULL);
2058  assert(blkmem != NULL);
2059 
2060  /* create variable */
2061  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2062  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2063 
2064  /* create event filter for transformed variable */
2065  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2066 
2067  /* set variable status and data */
2068  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2069 
2070  /* capture variable */
2071  SCIPvarCapture(*var);
2072 
2073  return SCIP_OKAY;
2074 }
2075 
2076 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2077  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2078  * copied at all
2079  */
2081  SCIP_VAR** var, /**< pointer to store the target variable */
2082  BMS_BLKMEM* blkmem, /**< block memory */
2083  SCIP_SET* set, /**< global SCIP settings */
2084  SCIP_STAT* stat, /**< problem statistics */
2085  SCIP* sourcescip, /**< source SCIP data structure */
2086  SCIP_VAR* sourcevar, /**< source variable */
2087  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2088  * target variables */
2089  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2090  * target constraints */
2091  SCIP_Bool global /**< should global or local bounds be used? */
2092  )
2093 {
2094  SCIP_VARDATA* targetdata;
2095  SCIP_RESULT result;
2096  SCIP_Real lb;
2097  SCIP_Real ub;
2098 
2099  assert(set != NULL);
2100  assert(blkmem != NULL);
2101  assert(stat != NULL);
2102  assert(sourcescip != NULL);
2103  assert(sourcevar != NULL);
2104  assert(var != NULL);
2105  assert(set->stage == SCIP_STAGE_PROBLEM);
2106  assert(varmap != NULL);
2107  assert(consmap != NULL);
2108 
2109  /** @todo copy hole lists */
2110  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2111  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2112 
2113  result = SCIP_DIDNOTRUN;
2114  targetdata = NULL;
2115 
2116  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2117  {
2118  lb = SCIPvarGetLbOriginal(sourcevar);
2119  ub = SCIPvarGetUbOriginal(sourcevar);
2120  }
2121  else
2122  {
2123  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2124  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2125  }
2126 
2127  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2128  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2129  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2130  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2131  NULL, NULL, NULL, NULL, NULL) );
2132  assert(*var != NULL);
2133 
2134  /* insert variable into mapping between source SCIP and the target SCIP */
2135  assert(!SCIPhashmapExists(varmap, sourcevar));
2136  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2137 
2138  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2139  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2140  {
2141  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2142  varmap, consmap, (*var), &targetdata, &result) );
2143 
2144  /* evaluate result */
2145  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2146  {
2147  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2148  return SCIP_INVALIDRESULT;
2149  }
2150 
2151  assert(targetdata == NULL || result == SCIP_SUCCESS);
2152  }
2153 
2154  /* we initialize histories of the variables by copying the source variable-information */
2155  if( set->history_allowtransfer )
2156  {
2157  SCIPvarMergeHistories((*var), sourcevar, stat);
2158  }
2159 
2160  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2161  * methods
2162  */
2163  if( result == SCIP_SUCCESS )
2164  {
2165  (*var)->varcopy = sourcevar->varcopy;
2166  (*var)->vardelorig = sourcevar->vardelorig;
2167  (*var)->vartrans = sourcevar->vartrans;
2168  (*var)->vardeltrans = sourcevar->vardeltrans;
2169  (*var)->vardata = targetdata;
2170  }
2171 
2172  SCIPdebugMessage("created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2173 
2174  return SCIP_OKAY;
2175 }
2176 
2177 /** parse given string for a SCIP_Real bound */
2178 static
2180  SCIP_SET* set, /**< global SCIP settings */
2181  const char* str, /**< string to parse */
2182  SCIP_Real* value, /**< pointer to store the parsed value */
2183  char** endptr /**< pointer to store the final string position if successfully parsed */
2184  )
2185 {
2186  /* first check for infinity value */
2187  if( strncmp(str, "+inf", 4) == 0 )
2188  {
2189  *value = SCIPsetInfinity(set);
2190  (*endptr) = (char*)str + 4;
2191  }
2192  else if( strncmp(str, "-inf", 4) == 0 )
2193  {
2194  *value = -SCIPsetInfinity(set);
2195  (*endptr) = (char*)str + 4;
2196  }
2197  else
2198  {
2199  if( !SCIPstrToRealValue(str, value, endptr) )
2200  return SCIP_READERROR;
2201  }
2202 
2203  return SCIP_OKAY;
2204 }
2205 
2206 /** parse the characters as bounds */
2207 static
2209  SCIP_SET* set, /**< global SCIP settings */
2210  const char* str, /**< string to parse */
2211  char* type, /**< bound type (global, local, or lazy) */
2212  SCIP_Real* lb, /**< pointer to store the lower bound */
2213  SCIP_Real* ub, /**< pointer to store the upper bound */
2214  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2215  )
2216 {
2217  char token[SCIP_MAXSTRLEN];
2218 
2219  SCIPdebugMessage("parsing bounds: '%s'\n", str);
2220 
2221  /* get bound type */
2222  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2223  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2224  {
2225  SCIPdebugMessage("unkown bound type <%s>\n", type);
2226  *endptr = NULL;
2227  return SCIP_OKAY;
2228  }
2229 
2230  SCIPdebugMessage("parsed bound type <%s>\n", type);
2231 
2232  /* get lower bound */
2233  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2234  str = *endptr;
2235  SCIP_CALL( parseValue(set, token, lb, endptr) );
2236 
2237  /* get upper bound */
2238  SCIP_CALL( parseValue(set, str, ub, endptr) );
2239 
2240  SCIPdebugMessage("parsed bounds: [%g,%g]\n", *lb, *ub);
2241 
2242  /* skip end of bounds */
2243  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2244  ++(*endptr);
2245 
2246  return SCIP_OKAY;
2247 }
2248 
2249 /** parses a given string for a variable informations */
2250 static
2252  SCIP_SET* set, /**< global SCIP settings */
2253  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2254  const char* str, /**< string to parse */
2255  char* name, /**< pointer to store the variable name */
2256  SCIP_Real* lb, /**< pointer to store the lower bound */
2257  SCIP_Real* ub, /**< pointer to store the upper bound */
2258  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2259  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2260  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2261  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2262  SCIP_Bool local, /**< should the local bound be applied */
2263  char** endptr, /**< pointer to store the final string position if successfully */
2264  SCIP_Bool* success /**< pointer store if the paring process was successful */
2265  )
2266 {
2267  SCIP_Real parsedlb;
2268  SCIP_Real parsedub;
2269  char token[SCIP_MAXSTRLEN];
2270  char* strptr;
2271  int i;
2272 
2273  assert(lb != NULL);
2274  assert(ub != NULL);
2275  assert(obj != NULL);
2276  assert(vartype != NULL);
2277  assert(lazylb != NULL);
2278  assert(lazyub != NULL);
2279  assert(endptr != NULL);
2280  assert(success != NULL);
2281 
2282  (*success) = TRUE;
2283 
2284  /* copy variable type */
2285  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2286  assert(str != *endptr);
2287  SCIPdebugMessage("parsed variable type <%s>\n", token);
2288 
2289  /* get variable type */
2290  if( strncmp(token, "binary", 3) == 0 )
2291  (*vartype) = SCIP_VARTYPE_BINARY;
2292  else if( strncmp(token, "integer", 3) == 0 )
2293  (*vartype) = SCIP_VARTYPE_INTEGER;
2294  else if( strncmp(token, "implicit", 3) == 0 )
2295  (*vartype) = SCIP_VARTYPE_IMPLINT;
2296  else if( strncmp(token, "continuous", 3) == 0 )
2297  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2298  else
2299  {
2300  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2301  (*success) = FALSE;
2302  return SCIP_OKAY;
2303  }
2304 
2305  /* move string pointer behind variable type */
2306  str = *endptr;
2307 
2308  /* get variable name */
2309  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2310  assert(endptr != NULL);
2311  SCIPdebugMessage("parsed variable name <%s>\n", name);
2312 
2313  /* move string pointer behind variable name */
2314  str = *endptr;
2315 
2316  /* cut out objective coefficient */
2317  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2318 
2319  /* move string pointer behind objective coefficient */
2320  str = *endptr;
2321 
2322  /* get objective coefficient */
2323  if( !SCIPstrToRealValue(token, obj, endptr) )
2324  {
2325  *endptr = NULL;
2326  return SCIP_READERROR;
2327  }
2328 
2329  SCIPdebugMessage("parsed objective coefficient <%g>\n", *obj);
2330 
2331  /* parse global/original bounds */
2332  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2333  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2334 
2335  /* initialize the lazy bound */
2336  *lazylb = -SCIPsetInfinity(set);
2337  *lazyub = SCIPsetInfinity(set);
2338 
2339  /* store pointer */
2340  strptr = *endptr;
2341 
2342  /* possibly parse optional local and lazy bounds */
2343  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2344  {
2345  /* start after previous bounds */
2346  strptr = *endptr;
2347 
2348  /* parse global bounds */
2349  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2350 
2351  if( strncmp(token, "local", 5) == 0 && local )
2352  {
2353  *lb = parsedlb;
2354  *ub = parsedub;
2355  }
2356  else if( strncmp(token, "lazy", 4) == 0 )
2357  {
2358  *lazylb = parsedlb;
2359  *lazyub = parsedub;
2360  }
2361  }
2362 
2363  /* restore pointer */
2364  if ( *endptr == NULL )
2365  *endptr = strptr;
2366 
2367  /* check bounds for binary variables */
2368  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2369  {
2370  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2371  {
2372  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2373  return SCIP_READERROR;
2374  }
2375  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2376  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2377  {
2378  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2379  return SCIP_READERROR;
2380  }
2381  }
2382 
2383  return SCIP_OKAY;
2384 }
2385 
2386 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2387  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2388  * integer variable with bounds zero and one is automatically converted into a binary variable
2389  */
2391  SCIP_VAR** var, /**< pointer to variable data */
2392  BMS_BLKMEM* blkmem, /**< block memory */
2393  SCIP_SET* set, /**< global SCIP settings */
2394  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2395  SCIP_STAT* stat, /**< problem statistics */
2396  const char* str, /**< string to parse */
2397  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2398  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2399  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2400  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2401  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2402  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2403  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2404  char** endptr, /**< pointer to store the final string position if successfully */
2405  SCIP_Bool* success /**< pointer store if the paring process was successful */
2406  )
2407 {
2408  char name[SCIP_MAXSTRLEN];
2409  SCIP_Real lb;
2410  SCIP_Real ub;
2411  SCIP_Real obj;
2412  SCIP_VARTYPE vartype;
2413  SCIP_Real lazylb;
2414  SCIP_Real lazyub;
2415 
2416  assert(var != NULL);
2417  assert(blkmem != NULL);
2418  assert(stat != NULL);
2419  assert(endptr != NULL);
2420  assert(success != NULL);
2421 
2422  /* parse string in cip format for variable information */
2423  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2424 
2425  if( *success )
2426  {
2427  /* create variable */
2428  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2429  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2430 
2431  /* set variable status and data */
2432  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2433  (*var)->data.original.origdom.holelist = NULL;
2434  (*var)->data.original.origdom.lb = lb;
2435  (*var)->data.original.origdom.ub = ub;
2436  (*var)->data.original.transvar = NULL;
2437 
2438  /* set lazy status of variable bounds */
2439  (*var)->lazylb = lazylb;
2440  (*var)->lazyub = lazyub;
2441 
2442  /* capture variable */
2443  SCIPvarCapture(*var);
2444  }
2445 
2446  return SCIP_OKAY;
2447 }
2448 
2449 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2450  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2451  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2452  * variable
2453  */
2455  SCIP_VAR** var, /**< pointer to variable data */
2456  BMS_BLKMEM* blkmem, /**< block memory */
2457  SCIP_SET* set, /**< global SCIP settings */
2458  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2459  SCIP_STAT* stat, /**< problem statistics */
2460  const char* str, /**< string to parse */
2461  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2462  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2463  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2464  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2465  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2466  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2467  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2468  char** endptr, /**< pointer to store the final string position if successfully */
2469  SCIP_Bool* success /**< pointer store if the paring process was successful */
2470  )
2471 {
2472  char name[SCIP_MAXSTRLEN];
2473  SCIP_Real lb;
2474  SCIP_Real ub;
2475  SCIP_Real obj;
2476  SCIP_VARTYPE vartype;
2477  SCIP_Real lazylb;
2478  SCIP_Real lazyub;
2479 
2480  assert(var != NULL);
2481  assert(blkmem != NULL);
2482  assert(endptr != NULL);
2483  assert(success != NULL);
2484 
2485  /* parse string in cip format for variable information */
2486  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2487 
2488  if( *success )
2489  {
2490  /* create variable */
2491  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2492  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2493 
2494  /* create event filter for transformed variable */
2495  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2496 
2497  /* set variable status and data */
2498  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2499 
2500  /* set lazy status of variable bounds */
2501  (*var)->lazylb = lazylb;
2502  (*var)->lazyub = lazyub;
2503 
2504  /* capture variable */
2505  SCIPvarCapture(*var);
2506  }
2507 
2508  return SCIP_OKAY;
2509 }
2510 
2511 /** ensures, that parentvars array of var can store at least num entries */
2512 static
2514  SCIP_VAR* var, /**< problem variable */
2515  BMS_BLKMEM* blkmem, /**< block memory */
2516  SCIP_SET* set, /**< global SCIP settings */
2517  int num /**< minimum number of entries to store */
2518  )
2519 {
2520  assert(var->nparentvars <= var->parentvarssize);
2521 
2522  if( num > var->parentvarssize )
2523  {
2524  int newsize;
2525 
2526  newsize = SCIPsetCalcMemGrowSize(set, num);
2527  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2528  var->parentvarssize = newsize;
2529  }
2530  assert(num <= var->parentvarssize);
2531 
2532  return SCIP_OKAY;
2533 }
2534 
2535 /** adds variable to parent list of a variable and captures parent variable */
2536 static
2538  SCIP_VAR* var, /**< variable to add parent to */
2539  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2540  SCIP_SET* set, /**< global SCIP settings */
2541  SCIP_VAR* parentvar /**< parent variable to add */
2542  )
2543 {
2544  assert(var != NULL);
2545  assert(parentvar != NULL);
2546 
2547  /* the direct original counterpart must be stored as first parent */
2548  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2549 
2550  SCIPdebugMessage("adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2551  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2552 
2553  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2554 
2555  var->parentvars[var->nparentvars] = parentvar;
2556  var->nparentvars++;
2557 
2558  SCIPvarCapture(parentvar);
2559 
2560  return SCIP_OKAY;
2561 }
2562 
2563 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2564 static
2566  SCIP_VAR** var, /**< pointer to variable */
2567  BMS_BLKMEM* blkmem, /**< block memory */
2568  SCIP_SET* set, /**< global SCIP settings */
2569  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2570  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2571  )
2572 {
2573  SCIP_VAR* parentvar;
2574  int i;
2575 
2576  SCIPdebugMessage("free parents of <%s>\n", (*var)->name);
2577 
2578  /* release the parent variables and remove the link from the parent variable to the child */
2579  for( i = 0; i < (*var)->nparentvars; ++i )
2580  {
2581  assert((*var)->parentvars != NULL);
2582  parentvar = (*var)->parentvars[i];
2583  assert(parentvar != NULL);
2584 
2585  switch( SCIPvarGetStatus(parentvar) )
2586  {
2588  assert(parentvar->data.original.transvar == *var);
2589  assert(&parentvar->data.original.transvar != var);
2590  parentvar->data.original.transvar = NULL;
2591  break;
2592 
2594  assert(parentvar->data.aggregate.var == *var);
2595  assert(&parentvar->data.aggregate.var != var);
2596  parentvar->data.aggregate.var = NULL;
2597  break;
2598 
2599 #if 0
2600  /* The following code is unclear: should the current variable be removed from its parents? */
2602  assert(parentvar->data.multaggr.vars != NULL);
2603  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2604  {}
2605  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2606  if( v < parentvar->data.multaggr.nvars-1 )
2607  {
2608  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2609  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2610  }
2611  parentvar->data.multaggr.nvars--;
2612  break;
2613 #endif
2614 
2616  assert(parentvar->negatedvar == *var);
2617  assert((*var)->negatedvar == parentvar);
2618  parentvar->negatedvar = NULL;
2619  (*var)->negatedvar = NULL;
2620  break;
2621 
2622  default:
2623  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2624  return SCIP_INVALIDDATA;
2625  } /*lint !e788*/
2626 
2627  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2628  }
2629 
2630  /* free parentvars array */
2631  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2632 
2633  return SCIP_OKAY;
2634 }
2635 
2636 /** frees a variable */
2637 static
2639  SCIP_VAR** var, /**< pointer to variable */
2640  BMS_BLKMEM* blkmem, /**< block memory */
2641  SCIP_SET* set, /**< global SCIP settings */
2642  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2643  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2644  )
2645 {
2646  assert(var != NULL);
2647  assert(*var != NULL);
2648  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2649  assert((*var)->nuses == 0);
2650  assert((*var)->probindex == -1);
2651 
2652  SCIPdebugMessage("free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2653 
2654  switch( SCIPvarGetStatus(*var) )
2655  {
2657  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2658  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2659  assert((*var)->data.original.origdom.holelist == NULL);
2660  break;
2661  case SCIP_VARSTATUS_LOOSE:
2662  break;
2663  case SCIP_VARSTATUS_COLUMN:
2664  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2665  break;
2666  case SCIP_VARSTATUS_FIXED:
2668  break;
2670  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2671  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2672  break;
2674  break;
2675  default:
2676  SCIPerrorMessage("unknown variable status\n");
2677  return SCIP_INVALIDDATA;
2678  }
2679 
2680  /* release all parent variables and free the parentvars array */
2681  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2682 
2683  /* free user data */
2685  {
2686  if( (*var)->vardelorig != NULL )
2687  {
2688  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2689  }
2690  }
2691  else
2692  {
2693  if( (*var)->vardeltrans != NULL )
2694  {
2695  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2696  }
2697  }
2698 
2699  /* free event filter */
2700  if( (*var)->eventfilter != NULL )
2701  {
2702  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2703  }
2704  assert((*var)->eventfilter == NULL);
2705 
2706  /* free hole lists */
2707  holelistFree(&(*var)->glbdom.holelist, blkmem);
2708  holelistFree(&(*var)->locdom.holelist, blkmem);
2709  assert((*var)->glbdom.holelist == NULL);
2710  assert((*var)->locdom.holelist == NULL);
2711 
2712  /* free variable bounds data structures */
2713  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2714  SCIPvboundsFree(&(*var)->vubs, blkmem);
2715 
2716  /* free implications data structures */
2717  SCIPimplicsFree(&(*var)->implics, blkmem);
2718 
2719  /* free clique list data structures */
2720  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2721 
2722  /* free bound change information arrays */
2723  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2724  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2725 
2726  /* free branching and inference history entries */
2727  SCIPhistoryFree(&(*var)->history, blkmem);
2728  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2729  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2730 
2731  /* free variable data structure */
2732  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2733  BMSfreeBlockMemory(blkmem, var);
2734 
2735  return SCIP_OKAY;
2736 }
2737 
2738 /** increases usage counter of variable */
2739 void SCIPvarCapture(
2740  SCIP_VAR* var /**< variable */
2741  )
2742 {
2743  assert(var != NULL);
2744  assert(var->nuses >= 0);
2745 
2746  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2747  var->nuses++;
2748 }
2749 
2750 /** decreases usage counter of variable, and frees memory if necessary */
2752  SCIP_VAR** var, /**< pointer to variable */
2753  BMS_BLKMEM* blkmem, /**< block memory */
2754  SCIP_SET* set, /**< global SCIP settings */
2755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2756  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2757  )
2758 {
2759  assert(var != NULL);
2760  assert(*var != NULL);
2761  assert((*var)->nuses >= 1);
2762  assert(blkmem != NULL);
2763  assert((*var)->scip == set->scip);
2764 
2765  SCIPdebugMessage("release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2766  (*var)->nuses--;
2767  if( (*var)->nuses == 0 )
2768  {
2769  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2770  }
2771 
2772  *var = NULL;
2773 
2774  return SCIP_OKAY;
2775 }
2776 
2777 /** change variable name */
2779  SCIP_VAR* var, /**< problem variable */
2780  BMS_BLKMEM* blkmem, /**< block memory */
2781  const char* name /**< name of variable */
2782  )
2783 {
2784  assert(name != NULL);
2785 
2786  /* remove old variable name */
2787  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2788 
2789  /* set new variable name */
2790  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2791 
2792  return SCIP_OKAY;
2793 }
2794 
2795 /** initializes variable data structure for solving */
2796 void SCIPvarInitSolve(
2797  SCIP_VAR* var /**< problem variable */
2798  )
2799 {
2800  assert(var != NULL);
2801 
2803  var->conflictlbcount = 0;
2804  var->conflictubcount = 0;
2805 }
2806 
2807 /** outputs the given bounds into the file stream */
2808 static
2809 void printBounds(
2810  SCIP_SET* set, /**< global SCIP settings */
2811  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2812  FILE* file, /**< output file (or NULL for standard output) */
2813  SCIP_Real lb, /**< lower bound */
2814  SCIP_Real ub, /**< upper bound */
2815  const char* name /**< bound type name */
2816  )
2817 {
2818  assert(set != NULL);
2819 
2820  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2821  if( SCIPsetIsInfinity(set, lb) )
2822  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2823  else if( SCIPsetIsInfinity(set, -lb) )
2824  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2825  else
2826  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2827  if( SCIPsetIsInfinity(set, ub) )
2828  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2829  else if( SCIPsetIsInfinity(set, -ub) )
2830  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2831  else
2832  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2833 }
2834 
2835 /** prints hole list to file stream */
2836 static
2837 void printHolelist(
2838  SCIP_SET* set, /**< global SCIP settings */
2839  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2840  FILE* file, /**< output file (or NULL for standard output) */
2841  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2842  const char* name /**< hole type name */
2843  )
2844 { /*lint --e{715}*/
2845  SCIP_Real left;
2846  SCIP_Real right;
2847 
2848  if( holelist == NULL )
2849  return;
2850 
2851  left = SCIPholelistGetLeft(holelist);
2852  right = SCIPholelistGetRight(holelist);
2853 
2854  /* display first hole */
2855  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2856  holelist = SCIPholelistGetNext(holelist);
2857 
2858  while(holelist != NULL )
2859  {
2860  left = SCIPholelistGetLeft(holelist);
2861  right = SCIPholelistGetRight(holelist);
2862 
2863  /* display hole */
2864  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2865 
2866  /* get next hole */
2867  holelist = SCIPholelistGetNext(holelist);
2868  }
2869 }
2870 
2871 /** outputs variable information into file stream */
2873  SCIP_VAR* var, /**< problem variable */
2874  SCIP_SET* set, /**< global SCIP settings */
2875  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2876  FILE* file /**< output file (or NULL for standard output) */
2877  )
2878 {
2879  SCIP_HOLELIST* holelist;
2880  SCIP_Real lb;
2881  SCIP_Real ub;
2882  int i;
2883 
2884  assert(var != NULL);
2885  assert(var->scip == set->scip);
2886 
2887  /* type of variable */
2888  switch( SCIPvarGetType(var) )
2889  {
2890  case SCIP_VARTYPE_BINARY:
2891  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2892  break;
2893  case SCIP_VARTYPE_INTEGER:
2894  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2895  break;
2896  case SCIP_VARTYPE_IMPLINT:
2897  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2898  break;
2900  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2901  break;
2902  default:
2903  SCIPerrorMessage("unknown variable type\n");
2904  SCIPABORT();
2905  return SCIP_ERROR; /*lint !e527*/
2906  }
2907 
2908  /* name */
2909  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2910 
2911  /* objective value */
2912  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2913 
2914  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2915  if( !SCIPvarIsTransformed(var) )
2916  {
2917  /* output original bound */
2918  lb = SCIPvarGetLbOriginal(var);
2919  ub = SCIPvarGetUbOriginal(var);
2920  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2921 
2922  /* output lazy bound */
2923  lb = SCIPvarGetLbLazy(var);
2924  ub = SCIPvarGetUbLazy(var);
2925 
2926  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2927  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2928  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2929 
2930  holelist = SCIPvarGetHolelistOriginal(var);
2931  printHolelist(set, messagehdlr, file, holelist, "original holes");
2932  }
2933  else
2934  {
2935  /* output global bound */
2936  lb = SCIPvarGetLbGlobal(var);
2937  ub = SCIPvarGetUbGlobal(var);
2938  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2939 
2940  /* output local bound */
2941  lb = SCIPvarGetLbLocal(var);
2942  ub = SCIPvarGetUbLocal(var);
2943  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2944 
2945  /* output lazy bound */
2946  lb = SCIPvarGetLbLazy(var);
2947  ub = SCIPvarGetUbLazy(var);
2948 
2949  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2950  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2951  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2952 
2953  /* global hole list */
2954  holelist = SCIPvarGetHolelistGlobal(var);
2955  printHolelist(set, messagehdlr, file, holelist, "global holes");
2956 
2957  /* local hole list */
2958  holelist = SCIPvarGetHolelistLocal(var);
2959  printHolelist(set, messagehdlr, file, holelist, "local holes");
2960  }
2961 
2962  /* fixings and aggregations */
2963  switch( SCIPvarGetStatus(var) )
2964  {
2966  case SCIP_VARSTATUS_LOOSE:
2967  case SCIP_VARSTATUS_COLUMN:
2968  break;
2969 
2970  case SCIP_VARSTATUS_FIXED:
2971  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
2972  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
2973  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
2974  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
2975  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
2976  else
2977  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
2978  break;
2979 
2981  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2982  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
2983  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
2984  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
2985  break;
2986 
2988  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2989  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
2990  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
2991  for( i = 0; i < var->data.multaggr.nvars; ++i )
2992  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
2993  break;
2994 
2996  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
2997  break;
2998 
2999  default:
3000  SCIPerrorMessage("unknown variable status\n");
3001  SCIPABORT();
3002  return SCIP_ERROR; /*lint !e527*/
3003  }
3004 
3005  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3006 
3007  return SCIP_OKAY;
3008 }
3009 
3010 /** issues a VARUNLOCKED event on the given variable */
3011 static
3013  SCIP_VAR* var, /**< problem variable to change */
3014  BMS_BLKMEM* blkmem, /**< block memory */
3015  SCIP_SET* set, /**< global SCIP settings */
3016  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3017  )
3018 {
3019  SCIP_EVENT* event;
3020 
3021  assert(var != NULL);
3022  assert(var->nlocksdown <= 1 && var->nlocksup <= 1);
3023  assert(var->scip == set->scip);
3024 
3025  /* issue VARUNLOCKED event on variable */
3026  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3027  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3028 
3029  return SCIP_OKAY;
3030 }
3031 
3032 /** modifies lock numbers for rounding */
3034  SCIP_VAR* var, /**< problem variable */
3035  BMS_BLKMEM* blkmem, /**< block memory */
3036  SCIP_SET* set, /**< global SCIP settings */
3037  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3038  int addnlocksdown, /**< increase in number of rounding down locks */
3039  int addnlocksup /**< increase in number of rounding up locks */
3040  )
3041 {
3042  SCIP_VAR* lockvar;
3043 
3044  assert(var != NULL);
3045  assert(var->nlocksup >= 0);
3046  assert(var->nlocksdown >= 0);
3047  assert(var->scip == set->scip);
3048 
3049  if( addnlocksdown == 0 && addnlocksup == 0 )
3050  return SCIP_OKAY;
3051 
3052  SCIPdebugMessage("add rounding locks %d/%d to variable <%s> (locks=%d/%d)\n",
3053  addnlocksdown, addnlocksup, var->name, var->nlocksdown, var->nlocksup);
3054 
3055  lockvar = var;
3056 
3057  while( TRUE ) /*lint !e716 */
3058  {
3059  assert(lockvar != NULL);
3060 
3061  switch( SCIPvarGetStatus(lockvar) )
3062  {
3064  if( lockvar->data.original.transvar != NULL )
3065  {
3066  lockvar = lockvar->data.original.transvar;
3067  break;
3068  }
3069  else
3070  {
3071  lockvar->nlocksdown += addnlocksdown;
3072  lockvar->nlocksup += addnlocksup;
3073 
3074  assert(lockvar->nlocksdown >= 0);
3075  assert(lockvar->nlocksup >= 0);
3076 
3077  return SCIP_OKAY;
3078  }
3079  case SCIP_VARSTATUS_LOOSE:
3080  case SCIP_VARSTATUS_COLUMN:
3081  case SCIP_VARSTATUS_FIXED:
3082  lockvar->nlocksdown += addnlocksdown;
3083  lockvar->nlocksup += addnlocksup;
3084 
3085  assert(lockvar->nlocksdown >= 0);
3086  assert(lockvar->nlocksup >= 0);
3087 
3088  if( lockvar->nlocksdown <= 1 && lockvar->nlocksup <= 1 )
3089  {
3090  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3091  }
3092 
3093  return SCIP_OKAY;
3095  if( lockvar->data.aggregate.scalar < 0.0 )
3096  {
3097  int tmp = addnlocksup;
3098 
3099  addnlocksup = addnlocksdown;
3100  addnlocksdown = tmp;
3101  }
3102 
3103  lockvar = lockvar->data.aggregate.var;
3104  break;
3106  {
3107  int v;
3108 
3109  assert(!lockvar->donotmultaggr);
3110 
3111  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3112  {
3113  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3114  {
3115  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue,
3116  addnlocksdown, addnlocksup) );
3117  }
3118  else
3119  {
3120  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue,
3121  addnlocksup, addnlocksdown) );
3122  }
3123  }
3124  return SCIP_OKAY;
3125  }
3127  {
3128  int tmp = addnlocksup;
3129 
3130  assert(lockvar->negatedvar != NULL);
3131  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3132  assert(lockvar->negatedvar->negatedvar == lockvar);
3133 
3134  addnlocksup = addnlocksdown;
3135  addnlocksdown = tmp;
3136 
3137  lockvar = lockvar->negatedvar;
3138  break;
3139  }
3140  default:
3141  SCIPerrorMessage("unknown variable status\n");
3142  return SCIP_INVALIDDATA;
3143  }
3144  }
3145 }
3146 
3147 /** gets number of locks for rounding down */
3149  SCIP_VAR* var /**< problem variable */
3150  )
3151 {
3152  int nlocks;
3153  int i;
3154 
3155  assert(var != NULL);
3156  assert(var->nlocksdown >= 0);
3157 
3158  switch( SCIPvarGetStatus(var) )
3159  {
3161  if( var->data.original.transvar != NULL )
3163  else
3164  return var->nlocksdown;
3165 
3166  case SCIP_VARSTATUS_LOOSE:
3167  case SCIP_VARSTATUS_COLUMN:
3168  case SCIP_VARSTATUS_FIXED:
3169  return var->nlocksdown;
3170 
3172  if( var->data.aggregate.scalar > 0.0 )
3173  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3174  else
3175  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3176 
3178  assert(!var->donotmultaggr);
3179  nlocks = 0;
3180  for( i = 0; i < var->data.multaggr.nvars; ++i )
3181  {
3182  if( var->data.multaggr.scalars[i] > 0.0 )
3183  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3184  else
3185  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3186  }
3187  return nlocks;
3188 
3190  assert(var->negatedvar != NULL);
3192  assert(var->negatedvar->negatedvar == var);
3193  return SCIPvarGetNLocksUp(var->negatedvar);
3194 
3195  default:
3196  SCIPerrorMessage("unknown variable status\n");
3197  SCIPABORT();
3198  return INT_MAX; /*lint !e527*/
3199  }
3200 }
3201 
3202 /** gets number of locks for rounding up */
3203 int SCIPvarGetNLocksUp(
3204  SCIP_VAR* var /**< problem variable */
3205  )
3206 {
3207  int nlocks;
3208  int i;
3209 
3210  assert(var != NULL);
3211  assert(var->nlocksup >= 0);
3212 
3213  switch( SCIPvarGetStatus(var) )
3214  {
3216  if( var->data.original.transvar != NULL )
3218  else
3219  return var->nlocksup;
3220 
3221  case SCIP_VARSTATUS_LOOSE:
3222  case SCIP_VARSTATUS_COLUMN:
3223  case SCIP_VARSTATUS_FIXED:
3224  return var->nlocksup;
3225 
3227  if( var->data.aggregate.scalar > 0.0 )
3228  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3229  else
3230  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3231 
3233  assert(!var->donotmultaggr);
3234  nlocks = 0;
3235  for( i = 0; i < var->data.multaggr.nvars; ++i )
3236  {
3237  if( var->data.multaggr.scalars[i] > 0.0 )
3238  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3239  else
3240  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3241  }
3242  return nlocks;
3243 
3245  assert(var->negatedvar != NULL);
3247  assert(var->negatedvar->negatedvar == var);
3248  return SCIPvarGetNLocksDown(var->negatedvar);
3249 
3250  default:
3251  SCIPerrorMessage("unknown variable status\n");
3252  SCIPABORT();
3253  return INT_MAX; /*lint !e527*/
3254  }
3255 }
3256 
3257 /** is it possible, to round variable down and stay feasible? */
3259  SCIP_VAR* var /**< problem variable */
3260  )
3261 {
3262  return (SCIPvarGetNLocksDown(var) == 0);
3263 }
3264 
3265 /** is it possible, to round variable up and stay feasible? */
3267  SCIP_VAR* var /**< problem variable */
3268  )
3269 {
3270  return (SCIPvarGetNLocksUp(var) == 0);
3271 }
3272 
3273 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3274  * a new transformed variable for this variable is created
3275  */
3277  SCIP_VAR* origvar, /**< original problem variable */
3278  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3279  SCIP_SET* set, /**< global SCIP settings */
3280  SCIP_STAT* stat, /**< problem statistics */
3281  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3282  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3283  )
3284 {
3285  char name[SCIP_MAXSTRLEN];
3286 
3287  assert(origvar != NULL);
3288  assert(origvar->scip == set->scip);
3289  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3290  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3291  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3292  assert(origvar->vlbs == NULL);
3293  assert(origvar->vubs == NULL);
3294  assert(transvar != NULL);
3295 
3296  /* check if variable is already transformed */
3297  if( origvar->data.original.transvar != NULL )
3298  {
3299  *transvar = origvar->data.original.transvar;
3300  SCIPvarCapture(*transvar);
3301  }
3302  else
3303  {
3304  /* create transformed variable */
3305  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3306  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3307  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3308  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3309  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3310 
3311  /* copy the branch factor and priority */
3312  (*transvar)->branchfactor = origvar->branchfactor;
3313  (*transvar)->branchpriority = origvar->branchpriority;
3314  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3315 
3316  /* duplicate hole lists */
3317  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3318  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3319 
3320  /* link original and transformed variable */
3321  origvar->data.original.transvar = *transvar;
3322  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3323 
3324  /* copy rounding locks */
3325  (*transvar)->nlocksdown = origvar->nlocksdown;
3326  (*transvar)->nlocksup = origvar->nlocksup;
3327  assert((*transvar)->nlocksdown >= 0);
3328  assert((*transvar)->nlocksup >= 0);
3329 
3330  /* copy doNotMultiaggr status */
3331  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3332 
3333  /* copy lazy bounds */
3334  (*transvar)->lazylb = origvar->lazylb;
3335  (*transvar)->lazyub = origvar->lazyub;
3336 
3337  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3338  * when original variable was created
3339  */
3340  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3341 
3342  /* transform user data */
3343  if( origvar->vartrans != NULL )
3344  {
3345  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3346  }
3347  else
3348  (*transvar)->vardata = origvar->vardata;
3349  }
3350 
3351  SCIPdebugMessage("transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3352 
3353  return SCIP_OKAY;
3354 }
3355 
3356 /** gets corresponding transformed variable of an original or negated original variable */
3358  SCIP_VAR* origvar, /**< original problem variable */
3359  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3360  SCIP_SET* set, /**< global SCIP settings */
3361  SCIP_STAT* stat, /**< problem statistics */
3362  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3363  )
3364 {
3365  assert(origvar != NULL);
3367  assert(origvar->scip == set->scip);
3368 
3369  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3370  {
3371  assert(origvar->negatedvar != NULL);
3373 
3374  if( origvar->negatedvar->data.original.transvar == NULL )
3375  *transvar = NULL;
3376  else
3377  {
3378  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3379  }
3380  }
3381  else
3382  *transvar = origvar->data.original.transvar;
3383 
3384  return SCIP_OKAY;
3385 }
3386 
3387 /** converts loose transformed variable into column variable, creates LP column */
3389  SCIP_VAR* var, /**< problem variable */
3390  BMS_BLKMEM* blkmem, /**< block memory */
3391  SCIP_SET* set, /**< global SCIP settings */
3392  SCIP_STAT* stat, /**< problem statistics */
3393  SCIP_PROB* prob, /**< problem data */
3394  SCIP_LP* lp /**< current LP data */
3395  )
3396 {
3397  assert(var != NULL);
3398  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3399  assert(var->scip == set->scip);
3400 
3401  SCIPdebugMessage("creating column for variable <%s>\n", var->name);
3402 
3403  /* switch variable status */
3404  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3405 
3406  /* create column of variable */
3407  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3408 
3409  if( var->probindex != -1 )
3410  {
3411  /* inform problem about the variable's status change */
3412  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3413 
3414  /* inform LP, that problem variable is now a column variable and no longer loose */
3415  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3416  }
3417 
3418  return SCIP_OKAY;
3419 }
3420 
3421 /** converts column transformed variable back into loose variable, frees LP column */
3423  SCIP_VAR* var, /**< problem variable */
3424  BMS_BLKMEM* blkmem, /**< block memory */
3425  SCIP_SET* set, /**< global SCIP settings */
3426  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3427  SCIP_PROB* prob, /**< problem data */
3428  SCIP_LP* lp /**< current LP data */
3429  )
3430 {
3431  assert(var != NULL);
3432  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3433  assert(var->scip == set->scip);
3434  assert(var->data.col != NULL);
3435  assert(var->data.col->lppos == -1);
3436  assert(var->data.col->lpipos == -1);
3437 
3438  SCIPdebugMessage("deleting column for variable <%s>\n", var->name);
3439 
3440  /* free column of variable */
3441  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3442 
3443  /* switch variable status */
3444  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3445 
3446  if( var->probindex != -1 )
3447  {
3448  /* inform problem about the variable's status change */
3449  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3450 
3451  /* inform LP, that problem variable is now a loose variable and no longer a column */
3452  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3453  }
3454 
3455  return SCIP_OKAY;
3456 }
3457 
3458 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3459  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3460  * are not informed about a fixing of an active variable they are pointing to
3461  */
3462 static
3464  SCIP_VAR* var, /**< problem variable to change */
3465  BMS_BLKMEM* blkmem, /**< block memory */
3466  SCIP_SET* set, /**< global SCIP settings */
3467  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3468  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3469  * multi-aggregation(2)
3470  */
3471  )
3472 {
3473  SCIP_EVENT* event;
3474  SCIP_VARSTATUS varstatus;
3475  int i;
3476 
3477  assert(var != NULL);
3478  assert(var->scip == set->scip);
3479  assert(0 <= fixeventtype && fixeventtype <= 2);
3480 
3481  /* issue VARFIXED event on variable */
3482  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3483  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3484 
3485 #ifndef NDEBUG
3486  for( i = var->nparentvars -1; i >= 0; --i )
3487  {
3489  }
3490 #endif
3491 
3492  switch( fixeventtype )
3493  {
3494  case 0:
3495  /* process all parents of a fixed variable */
3496  for( i = var->nparentvars - 1; i >= 0; --i )
3497  {
3498  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3499 
3500  assert(varstatus != SCIP_VARSTATUS_FIXED);
3501 
3502  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3503  * one
3504  */
3505  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3506  {
3507  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3508  }
3509  }
3510  break;
3511  case 1:
3512  /* process all parents of a aggregated variable */
3513  for( i = var->nparentvars - 1; i >= 0; --i )
3514  {
3515  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3516 
3517  assert(varstatus != SCIP_VARSTATUS_FIXED);
3518 
3519  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3520  * issued(, except the original one)
3521  *
3522  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3523  * yet issued
3524  */
3525  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3526  continue;
3527 
3528  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3529  {
3530  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3531  }
3532  }
3533  break;
3534  case 2:
3535  /* process all parents of a aggregated variable */
3536  for( i = var->nparentvars - 1; i >= 0; --i )
3537  {
3538  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3539 
3540  assert(varstatus != SCIP_VARSTATUS_FIXED);
3541 
3542  /* issue event on all parent variables except the original one */
3543  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3544  {
3545  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3546  }
3547  }
3548  break;
3549  default:
3550  SCIPerrorMessage("unknown variable fixation event origin\n");
3551  return SCIP_INVALIDDATA;
3552  }
3553 
3554  return SCIP_OKAY;
3555 }
3556 
3557 /** converts variable into fixed variable */
3559  SCIP_VAR* var, /**< problem variable */
3560  BMS_BLKMEM* blkmem, /**< block memory */
3561  SCIP_SET* set, /**< global SCIP settings */
3562  SCIP_STAT* stat, /**< problem statistics */
3563  SCIP_PROB* transprob, /**< tranformed problem data */
3564  SCIP_PROB* origprob, /**< original problem data */
3565  SCIP_PRIMAL* primal, /**< primal data */
3566  SCIP_TREE* tree, /**< branch and bound tree */
3567  SCIP_REOPT* reopt, /**< reoptimization data structure */
3568  SCIP_LP* lp, /**< current LP data */
3569  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3570  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3571  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3572  SCIP_Real fixedval, /**< value to fix variable at */
3573  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3574  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3575  )
3576 {
3577  SCIP_Real obj;
3578  SCIP_Real childfixedval;
3579 
3580  assert(var != NULL);
3581  assert(var->scip == set->scip);
3582  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3583  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3584  assert(infeasible != NULL);
3585  assert(fixed != NULL);
3586 
3587  SCIPdebugMessage("fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3588 
3589  *infeasible = FALSE;
3590  *fixed = FALSE;
3591 
3593  {
3594  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3595  SCIPdebugMessage(" -> variable already fixed to %g (fixedval=%g): infeasible=%u\n",
3596  var->locdom.lb, fixedval, *infeasible);
3597  return SCIP_OKAY;
3598  }
3599  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3600  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3601  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3602  {
3603  SCIPdebugMessage(" -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3604  *infeasible = TRUE;
3605  return SCIP_OKAY;
3606  }
3607 
3608  switch( SCIPvarGetStatus(var) )
3609  {
3611  if( var->data.original.transvar == NULL )
3612  {
3613  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3614  return SCIP_INVALIDDATA;
3615  }
3616  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3617  lp, branchcand, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3618  break;
3619 
3620  case SCIP_VARSTATUS_LOOSE:
3621  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3622 
3623  /* set the fixed variable's objective value to 0.0 */
3624  obj = var->obj;
3625  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3626 
3627  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3628  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3629  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3630  * objective of this variable is set to zero
3631  */
3632  SCIPlpDecNLoosevars(lp);
3633 
3634  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3635  holelistFree(&var->glbdom.holelist, blkmem);
3636  holelistFree(&var->locdom.holelist, blkmem);
3637  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3638  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3639 
3640  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3641  var->glbdom.lb = fixedval;
3642  var->glbdom.ub = fixedval;
3643  var->locdom.lb = fixedval;
3644  var->locdom.ub = fixedval;
3645 
3646  /* delete implications and variable bounds information */
3647  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3648  assert(var->vlbs == NULL);
3649  assert(var->vubs == NULL);
3650  assert(var->implics == NULL);
3651  assert(var->cliquelist == NULL);
3652 
3653  /* clear the history of the variable */
3654  SCIPhistoryReset(var->history);
3656 
3657  /* convert variable into fixed variable */
3658  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3659 
3660  /* inform problem about the variable's status change */
3661  if( var->probindex != -1 )
3662  {
3663  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3664  }
3665 
3666  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3667  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
3668 
3669  /* issue VARFIXED event */
3670  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3671 
3672  *fixed = TRUE;
3673  break;
3674 
3675  case SCIP_VARSTATUS_COLUMN:
3676  SCIPerrorMessage("cannot fix a column variable\n");
3677  return SCIP_INVALIDDATA;
3678 
3679  case SCIP_VARSTATUS_FIXED:
3680  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3681  SCIPABORT(); /* case is already handled in earlier if condition */
3682  return SCIP_INVALIDDATA; /*lint !e527*/
3683 
3685  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3686  assert(SCIPsetIsZero(set, var->obj));
3687  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3688  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3689  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3690  else
3691  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3692  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3693  branchcand, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3694  break;
3695 
3697  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3698  SCIPABORT();
3699  return SCIP_INVALIDDATA; /*lint !e527*/
3700 
3702  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3703  assert(SCIPsetIsZero(set, var->obj));
3704  assert(var->negatedvar != NULL);
3706  assert(var->negatedvar->negatedvar == var);
3707  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3708  branchcand, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3709  break;
3710 
3711  default:
3712  SCIPerrorMessage("unknown variable status\n");
3713  return SCIP_INVALIDDATA;
3714  }
3715 
3716  return SCIP_OKAY;
3717 }
3718 
3719 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3720  *
3721  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3722  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3723  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3724  *
3725  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3726  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3727  */
3729  SCIP_SET* set, /**< global SCIP settings */
3730  SCIP_VAR** vars, /**< variable array to get active variables */
3731  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3732  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3733  int varssize, /**< available slots in vars and scalars array */
3734  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3735  int* requiredsize, /**< pointer to store the required array size for the active variables */
3736  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3737  )
3738 {
3739  SCIP_VAR** activevars;
3740  SCIP_Real* activescalars;
3741  int nactivevars;
3742  SCIP_Real activeconstant;
3743  SCIP_Bool activeconstantinf;
3744  int activevarssize;
3745 
3746  SCIP_VAR* var;
3747  SCIP_Real scalar;
3748  int v;
3749 
3750  SCIP_VAR** tmpvars;
3751  SCIP_VAR** multvars;
3752  SCIP_Real* tmpscalars;
3753  SCIP_Real* multscalars;
3754  int tmpvarssize;
3755  int ntmpvars;
3756  int nmultvars;
3757 
3758  SCIP_VAR* multvar;
3759  SCIP_Real multscalar;
3760  SCIP_Real multconstant;
3761  int pos;
3762 
3763  int noldtmpvars;
3764 
3765  SCIP_VAR** tmpvars2;
3766  SCIP_Real* tmpscalars2;
3767  int tmpvarssize2;
3768  int ntmpvars2;
3769 
3770  assert(set != NULL);
3771  assert(nvars != NULL);
3772  assert(vars != NULL || *nvars == 0);
3773  assert(scalars != NULL || *nvars == 0);
3774  assert(constant != NULL);
3775  assert(requiredsize != NULL);
3776  assert(*nvars <= varssize);
3777 
3778  *requiredsize = 0;
3779 
3780  if( *nvars == 0 )
3781  return SCIP_OKAY;
3782 
3783  assert(vars != NULL);
3784 
3785  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3786  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3787  {
3788  *requiredsize = 1;
3789 
3790  return SCIP_OKAY;
3791  }
3792 
3793  nactivevars = 0;
3794  activeconstant = 0.0;
3795  activeconstantinf = FALSE;
3796  activevarssize = (*nvars) * 2;
3797  ntmpvars = *nvars;
3798  tmpvarssize = *nvars;
3799 
3800  tmpvarssize2 = 1;
3801  ntmpvars2 = 0;
3802 
3803  /* allocate temporary memory */
3804  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3805  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3806  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3807  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3808  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3809  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3810 
3811  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3812  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3813  */
3814  for( v = ntmpvars - 1; v >= 0; --v )
3815  {
3816  var = tmpvars[v];
3817  scalar = tmpscalars[v];
3818 
3819  assert(var != NULL);
3820  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3821  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3822  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3823  */
3824  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3825  assert(var != NULL);
3826 
3827  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3828  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3829 
3830  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3831 
3832  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3833  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3836 
3837  tmpvars[v] = var;
3838  tmpscalars[v] = scalar;
3839  }
3840  noldtmpvars = ntmpvars;
3841 
3842  /* sort all variables to combine equal variables easily */
3843  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3844  for( v = ntmpvars - 1; v > 0; --v )
3845  {
3846  /* combine same variables */
3847  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
3848  {
3849  tmpscalars[v - 1] += tmpscalars[v];
3850  --ntmpvars;
3851  tmpvars[v] = tmpvars[ntmpvars];
3852  tmpscalars[v] = tmpscalars[ntmpvars];
3853  }
3854  }
3855  /* sort all variables again to combine equal variables later on */
3856  if( noldtmpvars > ntmpvars )
3857  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3858 
3859  /* collect for each variable the representation in active variables */
3860  while( ntmpvars >= 1 )
3861  {
3862  --ntmpvars;
3863  ntmpvars2 = 0;
3864  var = tmpvars[ntmpvars];
3865  scalar = tmpscalars[ntmpvars];
3866 
3867  assert(var != NULL);
3868 
3869  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3870  if( scalar == 0.0 )
3871  continue;
3872 
3873  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3874  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3877 
3878  switch( SCIPvarGetStatus(var) )
3879  {
3880  case SCIP_VARSTATUS_LOOSE:
3881  case SCIP_VARSTATUS_COLUMN:
3882  /* x = a*y + c */
3883  if( nactivevars >= activevarssize )
3884  {
3885  activevarssize *= 2;
3886  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3887  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3888  assert(nactivevars < activevarssize);
3889  }
3890  activevars[nactivevars] = var;
3891  activescalars[nactivevars] = scalar;
3892  nactivevars++;
3893  break;
3894 
3896  /* x = a_1*y_1 + ... + a_n*y_n + c */
3897  nmultvars = var->data.multaggr.nvars;
3898  multvars = var->data.multaggr.vars;
3899  multscalars = var->data.multaggr.scalars;
3900 
3901  if( nmultvars + ntmpvars > tmpvarssize )
3902  {
3903  while( nmultvars + ntmpvars > tmpvarssize )
3904  tmpvarssize *= 2;
3905  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3906  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3907  assert(nmultvars + ntmpvars <= tmpvarssize);
3908  }
3909 
3910  if( nmultvars > tmpvarssize2 )
3911  {
3912  while( nmultvars > tmpvarssize2 )
3913  tmpvarssize2 *= 2;
3914  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3915  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3916  assert(nmultvars <= tmpvarssize2);
3917  }
3918 
3919  --nmultvars;
3920 
3921  for( ; nmultvars >= 0; --nmultvars )
3922  {
3923  multvar = multvars[nmultvars];
3924  multscalar = multscalars[nmultvars];
3925  multconstant = 0;
3926 
3927  assert(multvar != NULL);
3928  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
3929  assert(multvar != NULL);
3930 
3931  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3932  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3935 
3936  if( !activeconstantinf )
3937  {
3938  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
3939 
3940  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
3941  {
3942  assert(scalar != 0.0);
3943  if( scalar * multconstant > 0.0 )
3944  {
3945  activeconstant = SCIPsetInfinity(set);
3946  activeconstantinf = TRUE;
3947  }
3948  else
3949  {
3950  activeconstant = -SCIPsetInfinity(set);
3951  activeconstantinf = TRUE;
3952  }
3953  }
3954  else
3955  activeconstant += scalar * multconstant;
3956  }
3957 #ifndef NDEBUG
3958  else
3959  {
3960  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
3961  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3962  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
3963  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3964  }
3965 #endif
3966 
3967  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
3968  {
3969  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
3970  tmpscalars[pos] += scalar * multscalar;
3971  }
3972  else
3973  {
3974  tmpvars2[ntmpvars2] = multvar;
3975  tmpscalars2[ntmpvars2] = scalar * multscalar;
3976  ++(ntmpvars2);
3977  assert(ntmpvars2 <= tmpvarssize2);
3978  }
3979  }
3980 
3981  /* sort all variables to combine equal variables easily */
3982  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
3983  for( v = ntmpvars2 - 1; v > 0; --v )
3984  {
3985  /* combine same variables */
3986  if( SCIPvarCompare(tmpvars2[v], tmpvars2[v - 1]) == 0 )
3987  {
3988  tmpscalars2[v - 1] += tmpscalars2[v];
3989  --ntmpvars2;
3990  tmpvars2[v] = tmpvars2[ntmpvars2];
3991  tmpscalars2[v] = tmpscalars2[ntmpvars2];
3992  }
3993  }
3994 
3995  for( v = 0; v < ntmpvars2; ++v )
3996  {
3997  tmpvars[ntmpvars] = tmpvars2[v];
3998  tmpscalars[ntmpvars] = tmpscalars2[v];
3999  ++(ntmpvars);
4000  assert(ntmpvars <= tmpvarssize);
4001  }
4002  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
4003 
4004  if( !activeconstantinf )
4005  {
4006  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4007 
4008  multconstant = SCIPvarGetMultaggrConstant(var);
4009 
4010  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4011  {
4012  assert(scalar != 0.0);
4013  if( scalar * multconstant > 0.0 )
4014  {
4015  activeconstant = SCIPsetInfinity(set);
4016  activeconstantinf = TRUE;
4017  }
4018  else
4019  {
4020  activeconstant = -SCIPsetInfinity(set);
4021  activeconstantinf = TRUE;
4022  }
4023  }
4024  else
4025  activeconstant += scalar * multconstant;
4026  }
4027 #ifndef NDEBUG
4028  else
4029  {
4030  multconstant = SCIPvarGetMultaggrConstant(var);
4031  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4032  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4033  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4034  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4035  }
4036 #endif
4037  break;
4038 
4039  case SCIP_VARSTATUS_FIXED:
4043  default:
4044  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4045  * fixed variables and is handled already
4046  */
4047  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4048  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4049  }
4050  }
4051 
4052  if( mergemultiples )
4053  {
4054  /* sort variable and scalar array by variable index */
4055  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4056 
4057  /* eliminate duplicates and count required size */
4058  v = nactivevars - 1;
4059  while( v > 0 )
4060  {
4061  /* combine both variable since they are the same */
4062  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4063  {
4064  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4065  {
4066  activescalars[v - 1] += activescalars[v];
4067  --nactivevars;
4068  activevars[v] = activevars[nactivevars];
4069  activescalars[v] = activescalars[nactivevars];
4070  }
4071  else
4072  {
4073  --nactivevars;
4074  activevars[v] = activevars[nactivevars];
4075  activescalars[v] = activescalars[nactivevars];
4076  --nactivevars;
4077  --v;
4078  activevars[v] = activevars[nactivevars];
4079  activescalars[v] = activescalars[nactivevars];
4080  }
4081  }
4082  --v;
4083  }
4084  }
4085  *requiredsize = nactivevars;
4086 
4087  if( varssize >= *requiredsize )
4088  {
4089  assert(vars != NULL);
4090 
4091  *nvars = *requiredsize;
4092 
4093  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4094  {
4095  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4096  if( activeconstantinf )
4097  (*constant) = activeconstant;
4098  else
4099  (*constant) += activeconstant;
4100  }
4101 #ifndef NDEBUG
4102  else
4103  {
4104  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4105  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4106  }
4107 #endif
4108 
4109  /* copy active variable and scalar array to the given arrays */
4110  for( v = 0; v < *nvars; ++v )
4111  {
4112  vars[v] = activevars[v];
4113  scalars[v] = activescalars[v]; /*lint !e613*/
4114  }
4115  }
4116 
4117  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4118  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4119 
4120  SCIPsetFreeBufferArray(set, &tmpvars2);
4121  SCIPsetFreeBufferArray(set, &tmpscalars2);
4122  SCIPsetFreeBufferArray(set, &tmpvars);
4123  SCIPsetFreeBufferArray(set, &tmpscalars);
4124  SCIPsetFreeBufferArray(set, &activevars);
4125  SCIPsetFreeBufferArray(set, &activescalars);
4126 
4127  return SCIP_OKAY;
4128 }
4129 
4130 
4131 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4133  SCIP_VAR* var, /**< problem variable */
4134  BMS_BLKMEM* blkmem, /**< block memory */
4135  SCIP_SET* set /**< global SCIP settings */
4136  )
4137 {
4138  SCIP_Real multconstant;
4139  int multvarssize;
4140  int nmultvars;
4141  int multrequiredsize;
4142 
4143  assert( var != NULL );
4144  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4145  assert(var->scip == set->scip);
4146 
4147  multconstant = var->data.multaggr.constant;
4148  nmultvars = var->data.multaggr.nvars;
4149  multvarssize = var->data.multaggr.varssize;
4150 
4151  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4152 
4153  if( multrequiredsize > multvarssize )
4154  {
4155  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4156  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4157  multvarssize = multrequiredsize;
4158  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4159  assert( multrequiredsize <= multvarssize );
4160  }
4161  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4162  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4163  * may loose performance hereby, since aggregated variables are easier to handle.
4164  *
4165  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4166  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4167  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4168  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4169  *
4170  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4171  *
4172  * The same issue appears in the SCIPvarGetProbvar...() methods.
4173  */
4174 
4175  var->data.multaggr.constant = multconstant;
4176  var->data.multaggr.nvars = nmultvars;
4177  var->data.multaggr.varssize = multvarssize;
4178 
4179  return SCIP_OKAY;
4180 }
4181 
4182 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4183  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4184  * the history merge is reasonable
4185  *
4186  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4187  * this corrupts the variable pseudo costs
4188  * @note Apply with care; no internal checks are performed if the two variables should be merged
4189  */
4191  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4192  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4193  SCIP_STAT* stat /**< problem statistics */
4194  )
4195 {
4196  /* merge only the history of the current run into the target history */
4197  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4198 
4199  /* apply the changes also to the global history */
4200  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4201 }
4202 
4203 
4204 
4205 /** tightens the bounds of both variables in aggregation x = a*y + c */
4206 static
4208  SCIP_VAR* var, /**< problem variable */
4209  BMS_BLKMEM* blkmem, /**< block memory */
4210  SCIP_SET* set, /**< global SCIP settings */
4211  SCIP_STAT* stat, /**< problem statistics */
4212  SCIP_PROB* transprob, /**< tranformed problem data */
4213  SCIP_PROB* origprob, /**< original problem data */
4214  SCIP_PRIMAL* primal, /**< primal data */
4215  SCIP_TREE* tree, /**< branch and bound tree */
4216  SCIP_REOPT* reopt, /**< reoptimization data structure */
4217  SCIP_LP* lp, /**< current LP data */
4218  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4219  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4220  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4221  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4222  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4223  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4224  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4225  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4226  )
4227 {
4228  SCIP_Real varlb;
4229  SCIP_Real varub;
4230  SCIP_Real aggvarlb;
4231  SCIP_Real aggvarub;
4232  SCIP_Bool aggvarbdschanged;
4233 
4234  assert(var != NULL);
4235  assert(var->scip == set->scip);
4236  assert(aggvar != NULL);
4237  assert(!SCIPsetIsZero(set, scalar));
4238  assert(infeasible != NULL);
4239  assert(fixed != NULL);
4240 
4241  *infeasible = FALSE;
4242  *fixed = FALSE;
4243 
4244  SCIPdebugMessage("updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n",
4245  var->name, scalar, aggvar->name, constant);
4246  SCIPdebugMessage(" old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4247  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4248 
4249  /* loop as long additional changes may be found */
4250  do
4251  {
4252  aggvarbdschanged = FALSE;
4253 
4254  /* update the bounds of the aggregated variable x in x = a*y + c */
4255  if( scalar > 0.0 )
4256  {
4257  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4258  varlb = -SCIPsetInfinity(set);
4259  else
4260  varlb = aggvar->glbdom.lb * scalar + constant;
4261  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4262  varub = SCIPsetInfinity(set);
4263  else
4264  varub = aggvar->glbdom.ub * scalar + constant;
4265  }
4266  else
4267  {
4268  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4269  varub = SCIPsetInfinity(set);
4270  else
4271  varub = aggvar->glbdom.lb * scalar + constant;
4272  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4273  varlb = -SCIPsetInfinity(set);
4274  else
4275  varlb = aggvar->glbdom.ub * scalar + constant;
4276  }
4277  varlb = MAX(varlb, var->glbdom.lb);
4278  varub = MIN(varub, var->glbdom.ub);
4279  SCIPvarAdjustLb(var, set, &varlb);
4280  SCIPvarAdjustUb(var, set, &varub);
4281 
4282  /* check the new bounds */
4283  if( SCIPsetIsGT(set, varlb, varub) )
4284  {
4285  /* the aggregation is infeasible */
4286  *infeasible = TRUE;
4287  return SCIP_OKAY;
4288  }
4289  else if( SCIPsetIsEQ(set, varlb, varub) )
4290  {
4291  /* the aggregated variable is fixed -> fix both variables */
4292  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4293  eventqueue, cliquetable, varlb, infeasible, fixed) );
4294  if( !(*infeasible) )
4295  {
4296  SCIP_Bool aggfixed;
4297 
4298  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4299  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4300  assert(*fixed == aggfixed);
4301  }
4302  return SCIP_OKAY;
4303  }
4304  else
4305  {
4306  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4307  {
4308  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4309  }
4310  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4311  {
4312  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4313  }
4314 
4315  /* update the hole list of the aggregation variable */
4316  /**@todo update hole list of aggregation variable */
4317  }
4318 
4319  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4320  if( scalar > 0.0 )
4321  {
4322  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4323  aggvarlb = -SCIPsetInfinity(set);
4324  else
4325  aggvarlb = (var->glbdom.lb - constant) / scalar;
4326  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4327  aggvarub = SCIPsetInfinity(set);
4328  else
4329  aggvarub = (var->glbdom.ub - constant) / scalar;
4330  }
4331  else
4332  {
4333  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4334  aggvarub = SCIPsetInfinity(set);
4335  else
4336  aggvarub = (var->glbdom.lb - constant) / scalar;
4337  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4338  aggvarlb = -SCIPsetInfinity(set);
4339  else
4340  aggvarlb = (var->glbdom.ub - constant) / scalar;
4341  }
4342  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4343  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4344  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4345  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4346 
4347  /* check the new bounds */
4348  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4349  {
4350  /* the aggregation is infeasible */
4351  *infeasible = TRUE;
4352  return SCIP_OKAY;
4353  }
4354  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4355  {
4356  /* the aggregation variable is fixed -> fix both variables */
4357  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4358  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4359  if( !(*infeasible) )
4360  {
4361  SCIP_Bool varfixed;
4362 
4363  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4364  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4365  assert(*fixed == varfixed);
4366  }
4367  return SCIP_OKAY;
4368  }
4369  else
4370  {
4371  SCIP_Real oldbd;
4372  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4373  {
4374  oldbd = aggvar->glbdom.lb;
4375  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4376  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4377  }
4378  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4379  {
4380  oldbd = aggvar->glbdom.ub;
4381  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4382  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4383  }
4384 
4385  /* update the hole list of the aggregation variable */
4386  /**@todo update hole list of aggregation variable */
4387  }
4388  }
4389  while( aggvarbdschanged );
4390 
4391  SCIPdebugMessage(" new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4392  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4393 
4394  return SCIP_OKAY;
4395 }
4396 
4397 /** converts loose variable into aggregated variable */
4399  SCIP_VAR* var, /**< loose problem variable */
4400  BMS_BLKMEM* blkmem, /**< block memory */
4401  SCIP_SET* set, /**< global SCIP settings */
4402  SCIP_STAT* stat, /**< problem statistics */
4403  SCIP_PROB* transprob, /**< tranformed problem data */
4404  SCIP_PROB* origprob, /**< original problem data */
4405  SCIP_PRIMAL* primal, /**< primal data */
4406  SCIP_TREE* tree, /**< branch and bound tree */
4407  SCIP_REOPT* reopt, /**< reoptimization data structure */
4408  SCIP_LP* lp, /**< current LP data */
4409  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4410  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4411  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4412  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4413  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4414  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4415  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4416  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4417  )
4418 {
4419  SCIP_VAR** vars;
4420  SCIP_Real* coefs;
4421  SCIP_Real* constants;
4422  SCIP_Real obj;
4423  SCIP_Real branchfactor;
4424  SCIP_Bool fixed;
4425  int branchpriority;
4426  int nlocksdown;
4427  int nlocksup;
4428  int nvbds;
4429  int i;
4430  int j;
4431 
4432  assert(var != NULL);
4433  assert(var->scip == set->scip);
4434  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4435  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4436  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4437  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4438  assert(infeasible != NULL);
4439  assert(aggregated != NULL);
4440 
4441  *infeasible = FALSE;
4442  *aggregated = FALSE;
4443 
4444  /* get active problem variable of aggregation variable */
4445  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4446 
4447  /* aggregation is a fixing, if the scalar is zero */
4448  if( SCIPsetIsZero(set, scalar) )
4449  {
4450  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4451  cliquetable, constant, infeasible, aggregated) );
4452  return SCIP_OKAY;
4453  }
4454 
4455  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4456  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4457  return SCIP_OKAY;
4458 
4459  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4460  * should be changed in the future
4461  */
4462  if( SCIPvarGetHolelistGlobal(var) != NULL )
4463  return SCIP_OKAY;
4464 
4465  assert(aggvar != NULL);
4466  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4467  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4468  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4469 
4470  SCIPdebugMessage("aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4471  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4472 
4473  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4474  if( var == aggvar )
4475  {
4476  if( SCIPsetIsEQ(set, scalar, 1.0) )
4477  *infeasible = !SCIPsetIsZero(set, constant);
4478  else
4479  {
4480  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4481  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4482  }
4483  return SCIP_OKAY;
4484  }
4485 
4486  /* tighten the bounds of aggregated and aggregation variable */
4487  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4488  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4489  if( *infeasible || fixed )
4490  {
4491  *aggregated = fixed;
4492  return SCIP_OKAY;
4493  }
4494 
4495  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4496  * aggregated variable
4497  */
4498  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4499  assert(var->cliquelist == NULL);
4500 
4501  /* set the aggregated variable's objective value to 0.0 */
4502  obj = var->obj;
4503  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4504 
4505  /* unlock all rounding locks */
4506  nlocksdown = var->nlocksdown;
4507  nlocksup = var->nlocksup;
4508  var->nlocksdown = 0;
4509  var->nlocksup = 0;
4510 
4511  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4512  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4513  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4514  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4515  {
4516  /* link both variables as negation pair */
4517  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4518  var->data.negate.constant = 1.0;
4519  var->negatedvar = aggvar;
4520  aggvar->negatedvar = var;
4521 
4522  /* copy doNotMultiaggr status */
4523  aggvar->donotmultaggr |= var->donotmultaggr;
4524 
4525  /* mark both variables to be non-deletable */
4527  SCIPvarMarkNotDeletable(aggvar);
4528  }
4529  else
4530  {
4531  /* convert variable into aggregated variable */
4532  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4533  var->data.aggregate.var = aggvar;
4534  var->data.aggregate.scalar = scalar;
4535  var->data.aggregate.constant = constant;
4536 
4537  /* copy doNotMultiaggr status */
4538  aggvar->donotmultaggr |= var->donotmultaggr;
4539 
4540  /* mark both variables to be non-deletable */
4542  SCIPvarMarkNotDeletable(aggvar);
4543  }
4544 
4545  /* make aggregated variable a parent of the aggregation variable */
4546  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4547 
4548  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variable */
4549  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
4550 
4551  /* move the variable bounds to the aggregation variable:
4552  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4553  * - free the variable bounds data structures
4554  */
4555  if( var->vlbs != NULL )
4556  {
4557  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4558  vars = SCIPvboundsGetVars(var->vlbs);
4559  coefs = SCIPvboundsGetCoefs(var->vlbs);
4560  constants = SCIPvboundsGetConstants(var->vlbs);
4561  for( i = 0; i < nvbds && !(*infeasible); ++i )
4562  {
4563  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4564  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4565  }
4566  }
4567  if( var->vubs != NULL )
4568  {
4569  nvbds = SCIPvboundsGetNVbds(var->vubs);
4570  vars = SCIPvboundsGetVars(var->vubs);
4571  coefs = SCIPvboundsGetCoefs(var->vubs);
4572  constants = SCIPvboundsGetConstants(var->vubs);
4573  for( i = 0; i < nvbds && !(*infeasible); ++i )
4574  {
4575  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4576  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4577  }
4578  }
4579  SCIPvboundsFree(&var->vlbs, blkmem);
4580  SCIPvboundsFree(&var->vubs, blkmem);
4581 
4582  /* move the implications to the aggregation variable:
4583  * - add all implications again to the variable, thus adding it to the aggregation variable
4584  * - free the implications data structures
4585  */
4586  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4587  {
4588  assert(SCIPvarIsBinary(var));
4589  for( i = 0; i < 2; ++i )
4590  {
4591  SCIP_VAR** implvars;
4592  SCIP_BOUNDTYPE* impltypes;
4593  SCIP_Real* implbounds;
4594  int nimpls;
4595 
4596  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4597  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4598  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4599  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4600 
4601  for( j = 0; j < nimpls && !(*infeasible); ++j )
4602  {
4603  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4604  * implication to the aggregated variable?
4605  */
4606  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4607  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4608  NULL) );
4609  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4610  }
4611  }
4612  }
4613  SCIPimplicsFree(&var->implics, blkmem);
4614 
4615  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4616  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4617  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4618  SCIPhistoryReset(var->history);
4620 
4621  /* update flags of aggregation variable */
4622  aggvar->removable &= var->removable;
4623 
4624  /* update branching factors and priorities of both variables to be the maximum of both variables */
4625  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4626  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4627  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4628  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4629  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4630  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4631 
4632  /* update branching direction of both variables to agree to a single direction */
4633  if( scalar >= 0.0 )
4634  {
4636  {
4638  }
4639  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4640  {
4642  }
4643  else if( var->branchdirection != aggvar->branchdirection )
4644  {
4646  }
4647  }
4648  else
4649  {
4651  {
4653  }
4654  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4655  {
4657  }
4658  else if( var->branchdirection != aggvar->branchdirection )
4659  {
4661  }
4662  }
4663 
4664  if( var->probindex != -1 )
4665  {
4666  /* inform problem about the variable's status change */
4667  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4668  }
4669 
4670  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4671  * variable and the problem's objective offset
4672  */
4673  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4674 
4675  /* issue VARFIXED event */
4676  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4677 
4678  *aggregated = TRUE;
4679 
4680  return SCIP_OKAY;
4681 }
4682 
4683 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4684  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4685  *
4686  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4687  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4688  */
4689 static
4691  SCIP_SET* set, /**< global SCIP settings */
4692  BMS_BLKMEM* blkmem, /**< block memory */
4693  SCIP_STAT* stat, /**< problem statistics */
4694  SCIP_PROB* transprob, /**< tranformed problem data */
4695  SCIP_PROB* origprob, /**< original problem data */
4696  SCIP_PRIMAL* primal, /**< primal data */
4697  SCIP_TREE* tree, /**< branch and bound tree */
4698  SCIP_REOPT* reopt, /**< reoptimization data structure */
4699  SCIP_LP* lp, /**< current LP data */
4700  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4701  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4702  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4703  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4704  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4705  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4706  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4707  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4708  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4709  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4710  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4711  )
4712 {
4713  SCIP_VAR* aggvar;
4714  char aggvarname[SCIP_MAXSTRLEN];
4715  SCIP_Longint scalarxn = 0;
4716  SCIP_Longint scalarxd = 0;
4717  SCIP_Longint scalaryn = 0;
4718  SCIP_Longint scalaryd = 0;
4719  SCIP_Longint a;
4720  SCIP_Longint b;
4721  SCIP_Longint c;
4722  SCIP_Longint scm;
4723  SCIP_Longint gcd;
4724  SCIP_Longint currentclass;
4725  SCIP_Longint classstep;
4726  SCIP_Longint xsol;
4727  SCIP_Longint ysol;
4728  SCIP_Bool success;
4729  SCIP_VARTYPE vartype;
4730 
4731 #define MAXDNOM 1000000LL
4732 
4733  assert(set != NULL);
4734  assert(blkmem != NULL);
4735  assert(stat != NULL);
4736  assert(transprob != NULL);
4737  assert(origprob != NULL);
4738  assert(tree != NULL);
4739  assert(lp != NULL);
4740  assert(cliquetable != NULL);
4741  assert(branchcand != NULL);
4742  assert(eventqueue != NULL);
4743  assert(varx != NULL);
4744  assert(vary != NULL);
4745  assert(varx != vary);
4746  assert(infeasible != NULL);
4747  assert(aggregated != NULL);
4748  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4749  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4751  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4753  assert(!SCIPsetIsZero(set, scalarx));
4754  assert(!SCIPsetIsZero(set, scalary));
4755 
4756  *infeasible = FALSE;
4757  *aggregated = FALSE;
4758 
4759  /* get rational representation of coefficients */
4760  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4761  if( success )
4762  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4763  if( !success )
4764  return SCIP_OKAY;
4765  assert(scalarxd >= 1);
4766  assert(scalaryd >= 1);
4767 
4768  /* multiply equality with smallest common denominator */
4769  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4770  a = (scm/scalarxd)*scalarxn;
4771  b = (scm/scalaryd)*scalaryn;
4772  rhs *= scm;
4773 
4774  /* divide equality by the greatest common divisor of a and b */
4775  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4776  a /= gcd;
4777  b /= gcd;
4778  rhs /= gcd;
4779  assert(a != 0);
4780  assert(b != 0);
4781 
4782  /* check, if right hand side is integral */
4783  if( !SCIPsetIsFeasIntegral(set, rhs) )
4784  {
4785  *infeasible = TRUE;
4786  return SCIP_OKAY;
4787  }
4788  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4789 
4790  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4791  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4792  {
4793  /* aggregate x = - b/a*y + c/a */
4794  /*lint --e{653}*/
4795  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4796  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4797  assert(*aggregated);
4798  return SCIP_OKAY;
4799  }
4800  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4801  {
4802  /* aggregate y = - a/b*x + c/b */
4803  /*lint --e{653}*/
4804  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4805  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4806  assert(*aggregated);
4807  return SCIP_OKAY;
4808  }
4809 
4810  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4811  * common divisor. Let (x',y') be a solution of the equality
4812  * a*x + b*y == c -> a*x == c - b*y
4813  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4814  */
4815 
4816  /* find initial solution (x',y'):
4817  * - find y' such that c - b*y' is a multiple of a
4818  * - start in equivalence class c%a
4819  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
4820  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
4821  * - because a and b don't have a common divisor, each class is visited at most once, and at most a-1 steps are needed
4822  * - calculate x' with x' = (c - b*y')/a (which must be integral)
4823  *
4824  * Algorithm works for a > 0 only.
4825  */
4826  if( a < 0 )
4827  {
4828  a = -a;
4829  b = -b;
4830  c = -c;
4831  }
4832  assert(0 <= a);
4833 
4834  /* search upwards from ysol = 0 */
4835  ysol = 0;
4836  currentclass = c%a;
4837  if( currentclass < 0 )
4838  currentclass += a;
4839  assert(0 <= currentclass && currentclass < a);
4840 
4841  classstep = (-b)%a;
4842 
4843  if( classstep < 0 )
4844  classstep += a;
4845  assert(0 <= classstep && classstep < a);
4846 
4847  while( currentclass != 0 )
4848  {
4849  assert(0 <= currentclass && currentclass < a);
4850  currentclass += classstep;
4851  if( currentclass >= a )
4852  currentclass -= a;
4853  ysol++;
4854  }
4855  assert(ysol < a);
4856  assert(((c - b*ysol)%a) == 0);
4857 
4858  xsol = (c - b*ysol)/a;
4859 
4860  /* determine variable type for new artificial variable:
4861  *
4862  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
4863  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
4864  * integral type
4865  */
4868 
4869  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
4870  * - create new integer variable z with infinite bounds
4871  * - aggregate variable x = -b*z + x'
4872  * - aggregate variable y = a*z + y'
4873  * - the bounds of z are calculated automatically during aggregation
4874  */
4875  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
4876  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
4877  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
4879  NULL, NULL, NULL, NULL, NULL) );
4880 
4881  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
4882 
4883  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4884  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
4885  assert(*aggregated || *infeasible);
4886 
4887  if( !(*infeasible) )
4888  {
4889  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4890  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
4891  assert(*aggregated || *infeasible);
4892  }
4893 
4894  /* release z */
4895  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
4896 
4897  return SCIP_OKAY;
4898 }
4899 
4900 /** performs second step of SCIPaggregateVars():
4901  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
4902  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
4903  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
4904  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
4905  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
4906  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4907  *
4908  * @todo check for fixings, infeasibility, bound changes, or domain holes:
4909  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
4910  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
4911  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
4912  */
4914  SCIP_SET* set, /**< global SCIP settings */
4915  BMS_BLKMEM* blkmem, /**< block memory */
4916  SCIP_STAT* stat, /**< problem statistics */
4917  SCIP_PROB* transprob, /**< tranformed problem data */
4918  SCIP_PROB* origprob, /**< original problem data */
4919  SCIP_PRIMAL* primal, /**< primal data */
4920  SCIP_TREE* tree, /**< branch and bound tree */
4921  SCIP_REOPT* reopt, /**< reoptimization data structure */
4922  SCIP_LP* lp, /**< current LP data */
4923  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4924  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4925  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4926  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4927  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
4928  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
4929  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4930  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4931  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4932  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4933  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4934  )
4935 {
4936  SCIP_Bool easyaggr;
4937 
4938  assert(set != NULL);
4939  assert(blkmem != NULL);
4940  assert(stat != NULL);
4941  assert(transprob != NULL);
4942  assert(origprob != NULL);
4943  assert(tree != NULL);
4944  assert(lp != NULL);
4945  assert(cliquetable != NULL);
4946  assert(branchcand != NULL);
4947  assert(eventqueue != NULL);
4948  assert(varx != NULL);
4949  assert(vary != NULL);
4950  assert(varx != vary);
4951  assert(infeasible != NULL);
4952  assert(aggregated != NULL);
4953  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4954  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4955  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4956  assert(!SCIPsetIsZero(set, scalarx));
4957  assert(!SCIPsetIsZero(set, scalary));
4958 
4959  *infeasible = FALSE;
4960  *aggregated = FALSE;
4961 
4962  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
4963  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) || (SCIPvarGetType(vary) == SCIPvarGetType(varx) &&
4964  SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
4965  {
4966  SCIP_VAR* var;
4967  SCIP_Real scalar;
4968 
4969  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
4970  var = vary;
4971  vary = varx;
4972  varx = var;
4973  scalar = scalary;
4974  scalary = scalarx;
4975  scalarx = scalar;
4976  }
4977  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
4978 
4979  /* figure out, which variable should be aggregated */
4980  easyaggr = FALSE;
4981 
4982  /* check if it is an easy aggregation that means:
4983  *
4984  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
4985  */
4986  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
4987  {
4989  {
4990  easyaggr = TRUE;
4991  }
4992  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
4993  {
4994  easyaggr = TRUE;
4995  }
4996  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
4997  {
4998  /* we have an easy aggregation if we flip the variables x and y */
4999  SCIP_VAR* var;
5000  SCIP_Real scalar;
5001 
5002  /* switch the variables, such that varx is the aggregated variable */
5003  var = vary;
5004  vary = varx;
5005  varx = var;
5006  scalar = scalary;
5007  scalary = scalarx;
5008  scalarx = scalar;
5009  easyaggr = TRUE;
5010  }
5011  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5012  {
5013  /* the aggregation is still easy if both variables are continuous */
5014  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5015  easyaggr = TRUE;
5016  }
5017  }
5018 
5019  /* did we find an "easy" aggregation? */
5020  if( easyaggr )
5021  {
5022  SCIP_Real scalar;
5023  SCIP_Real constant;
5024 
5025  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5026 
5027  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5028  scalar = -scalary/scalarx;
5029  constant = rhs/scalarx;
5030 
5031  /* check aggregation for integer feasibility */
5034  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5035  {
5036  *infeasible = TRUE;
5037  return SCIP_OKAY;
5038  }
5039 
5040  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5041  * since then we would loose the corresponding divisibility property
5042  */
5043  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5044 
5045  /* aggregate the variable */
5046  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5047  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5048  assert(*aggregated || *infeasible);
5049  }
5052  {
5053  /* the variables are both integral: we have to try to find an integer aggregation */
5054  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5055  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5056  }
5057 
5058  return SCIP_OKAY;
5059 }
5060 
5061 /** converts variable into multi-aggregated variable */
5063  SCIP_VAR* var, /**< problem variable */
5064  BMS_BLKMEM* blkmem, /**< block memory */
5065  SCIP_SET* set, /**< global SCIP settings */
5066  SCIP_STAT* stat, /**< problem statistics */
5067  SCIP_PROB* transprob, /**< tranformed problem data */
5068  SCIP_PROB* origprob, /**< original problem data */
5069  SCIP_PRIMAL* primal, /**< primal data */
5070  SCIP_TREE* tree, /**< branch and bound tree */
5071  SCIP_REOPT* reopt, /**< reoptimization data structure */
5072  SCIP_LP* lp, /**< current LP data */
5073  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5074  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5075  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5076  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5077  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5078  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5079  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5080  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5081  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5082  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5083  )
5084 {
5085  SCIP_VAR** tmpvars;
5086  SCIP_Real* tmpscalars;
5087  SCIP_Real obj;
5088  SCIP_Real branchfactor;
5089  int branchpriority;
5090  SCIP_BRANCHDIR branchdirection;
5091  int nlocksdown;
5092  int nlocksup;
5093  int v;
5094  SCIP_Real tmpconstant;
5095  SCIP_Real tmpscalar;
5096  int ntmpvars;
5097  int tmpvarssize;
5098  int tmprequiredsize;
5099 
5100  assert(var != NULL);
5101  assert(var->scip == set->scip);
5102  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5103  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5104  assert(naggvars == 0 || aggvars != NULL);
5105  assert(naggvars == 0 || scalars != NULL);
5106  assert(infeasible != NULL);
5107  assert(aggregated != NULL);
5108 
5109  SCIPdebugMessage("trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5110 
5111  *infeasible = FALSE;
5112  *aggregated = FALSE;
5113 
5114  switch( SCIPvarGetStatus(var) )
5115  {
5117  if( var->data.original.transvar == NULL )
5118  {
5119  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5120  return SCIP_INVALIDDATA;
5121  }
5122  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5123  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5124  break;
5125 
5126  case SCIP_VARSTATUS_LOOSE:
5127  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5128 
5129  /* check if we would create a self-reference */
5130  ntmpvars = naggvars;
5131  tmpvarssize = naggvars;
5132  tmpconstant = constant;
5133  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5134  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5135 
5136  /* get all active variables for multi-aggregation */
5137  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5138  if( tmprequiredsize > tmpvarssize )
5139  {
5140  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5141  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5142  tmpvarssize = tmprequiredsize;
5143  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5144  assert( tmprequiredsize <= tmpvarssize );
5145  }
5146 
5147  tmpscalar = 0.0;
5148 
5149  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5150  * possible multi-aggregated variable
5151  */
5152  for( v = ntmpvars - 1; v >= 0; --v )
5153  {
5154  assert(tmpvars[v] != NULL);
5155  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5156 
5157  if( tmpvars[v]->index == var->index )
5158  {
5159  tmpscalar += tmpscalars[v];
5160  tmpvars[v] = tmpvars[ntmpvars - 1];
5161  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5162  --ntmpvars;
5163  }
5164  }
5165 
5166  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5167  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5168  {
5169  if( ntmpvars == 0 )
5170  {
5171  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5172  {
5173  SCIPdebugMessage("Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5174  goto TERMINATE;
5175  }
5176  else /* 0 = c and c != 0 */
5177  {
5178  SCIPdebugMessage("Multi-aggregation was completely resolved and led to infeasibility.\n");
5179  *infeasible = TRUE;
5180  goto TERMINATE;
5181  }
5182  }
5183  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5184  {
5185  assert(tmpscalars[0] != 0.0);
5186  assert(tmpvars[0] != NULL);
5187 
5188  SCIPdebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5189  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5190  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5191  goto TERMINATE;
5192  }
5193  else if( ntmpvars == 2 ) /* 0 = a_1*y_1 + a_2*y_2 + c => y_1 = -a_2/a_1 * y_2 - c/a_1 */
5194  {
5195  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5196 
5197  SCIPdebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5198  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5199 
5200  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5201  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5202  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5203 
5204  goto TERMINATE;
5205  }
5206  else
5207  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5208  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5209  */
5210  goto TERMINATE;
5211  }
5212  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5213  else if( !SCIPsetIsZero(set, tmpscalar) )
5214  {
5215  tmpscalar = 1 - tmpscalar;
5216  tmpconstant /= tmpscalar;
5217  for( v = ntmpvars - 1; v >= 0; --v )
5218  tmpscalars[v] /= tmpscalar;
5219  }
5220 
5221  /* check, if we are in one of the simple cases */
5222  if( ntmpvars == 0 )
5223  {
5224  SCIPdebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5225  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5226  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5227  goto TERMINATE;
5228  }
5229 
5230  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5231  if( ntmpvars == 1 )
5232  {
5233  SCIPdebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5234  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5235 
5236  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5237  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5238  infeasible, aggregated) );
5239 
5240  goto TERMINATE;
5241  }
5242 
5243  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5244  * empty hole list; this should be changed in the future */
5245  if( SCIPvarGetHolelistGlobal(var) != NULL )
5246  goto TERMINATE;
5247 
5248  /* if the variable is not allowed to be multi-aggregated */
5249  if( SCIPvarDoNotMultaggr(var) )
5250  {
5251  SCIPdebugMessage("variable is not allowed to be multi-aggregated.\n");
5252  goto TERMINATE;
5253  }
5254 
5255  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5256  * variable bound variable of another variable), we have to remove it from the other variables implications or
5257  * variable bounds
5258  */
5259  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5260  assert(var->vlbs == NULL);
5261  assert(var->vubs == NULL);
5262  assert(var->implics == NULL);
5263  assert(var->cliquelist == NULL);
5264 
5265  /* set the aggregated variable's objective value to 0.0 */
5266  obj = var->obj;
5267  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5268 
5269  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5270  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5271  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5272  * objective of this variable is set to zero
5273  */
5274  SCIPlpDecNLoosevars(lp);
5275 
5276  /* unlock all rounding locks */
5277  nlocksdown = var->nlocksdown;
5278  nlocksup = var->nlocksup;
5279  var->nlocksdown = 0;
5280  var->nlocksup = 0;
5281 
5282  /* convert variable into multi-aggregated variable */
5283  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5284  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5285  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5286  var->data.multaggr.constant = tmpconstant;
5287  var->data.multaggr.nvars = ntmpvars;
5288  var->data.multaggr.varssize = ntmpvars;
5289 
5290  /* mark variable to be non-deletable */
5292 
5293  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variables */
5294  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
5295 
5296  /* update flags and branching factors and priorities of aggregation variables;
5297  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5298  */
5299  branchfactor = var->branchfactor;
5300  branchpriority = var->branchpriority;
5301  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5302 
5303  for( v = 0; v < ntmpvars; ++v )
5304  {
5305  assert(tmpvars[v] != NULL);
5306  tmpvars[v]->removable &= var->removable;
5307  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5308  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5309 
5310  /* mark variable to be non-deletable */
5311  SCIPvarMarkNotDeletable(tmpvars[v]);
5312  }
5313  for( v = 0; v < ntmpvars; ++v )
5314  {
5315  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5316  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5317  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5318  {
5319  if( tmpscalars[v] >= 0.0 )
5320  {
5321  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5322  }
5323  else
5324  {
5325  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5326  }
5327  }
5328  }
5329  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5330  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5331 
5332  if( var->probindex != -1 )
5333  {
5334  /* inform problem about the variable's status change */
5335  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5336  }
5337 
5338  /* issue VARFIXED event */
5339  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5340 
5341  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5342  * variables and the problem's objective offset
5343  */
5344  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5345 
5346  *aggregated = TRUE;
5347 
5348  TERMINATE:
5349  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5350  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5351 
5352  break;
5353 
5354  case SCIP_VARSTATUS_COLUMN:
5355  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5356  return SCIP_INVALIDDATA;
5357 
5358  case SCIP_VARSTATUS_FIXED:
5359  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5360  return SCIP_INVALIDDATA;
5361 
5363  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5364  return SCIP_INVALIDDATA;
5365 
5367  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5368  return SCIP_INVALIDDATA;
5369 
5371  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5372  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5373  */
5374  assert(SCIPsetIsZero(set, var->obj));
5375  assert(var->negatedvar != NULL);
5377  assert(var->negatedvar->negatedvar == var);
5378 
5379  /* switch the signs of the aggregation scalars */
5380  for( v = 0; v < naggvars; ++v )
5381  scalars[v] *= -1.0;
5382 
5383  /* perform the multi aggregation on the negation variable */
5384  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5385  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5386  var->data.negate.constant - constant, infeasible, aggregated) );
5387 
5388  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5389  for( v = 0; v < naggvars; ++v )
5390  scalars[v] *= -1.0;
5391  break;
5392 
5393  default:
5394  SCIPerrorMessage("unknown variable status\n");
5395  return SCIP_INVALIDDATA;
5396  }
5397 
5398  return SCIP_OKAY;
5399 }
5400 
5401 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5402  * or for original variables the same variable is returned
5403  */
5404 static
5406  SCIP_VAR* var /**< problem variable */
5407  )
5408 {
5409  SCIP_VAR* retvar;
5410 
5411  assert(var != NULL);
5412 
5413  retvar = var;
5414 
5415  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5416 
5417  while( TRUE ) /*lint !e716 */
5418  {
5419  assert(retvar != NULL);
5420 
5421  switch( SCIPvarGetStatus(retvar) )
5422  {
5424  case SCIP_VARSTATUS_LOOSE:
5425  case SCIP_VARSTATUS_COLUMN:
5426  case SCIP_VARSTATUS_FIXED:
5427  return retvar;
5428 
5430  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5431  if ( retvar->data.multaggr.nvars == 1 )
5432  retvar = retvar->data.multaggr.vars[0];
5433  else
5434  return retvar;
5435  break;
5436 
5438  retvar = retvar->data.aggregate.var;
5439  break;
5440 
5442  retvar = retvar->negatedvar;
5443  break;
5444 
5445  default:
5446  SCIPerrorMessage("unknown variable status\n");
5447  SCIPABORT();
5448  return NULL; /*lint !e527*/
5449  }
5450  }
5451 }
5452 
5453 /** returns whether variable is not allowed to be multi-aggregated */
5455  SCIP_VAR* var /**< problem variable */
5456  )
5457 {
5458  SCIP_VAR* retvar;
5459 
5460  assert(var != NULL);
5461 
5462  retvar = varGetActiveVar(var);
5463  assert(retvar != NULL);
5464 
5465  switch( SCIPvarGetStatus(retvar) )
5466  {
5468  case SCIP_VARSTATUS_LOOSE:
5469  case SCIP_VARSTATUS_COLUMN:
5470  case SCIP_VARSTATUS_FIXED:
5471  return retvar->donotmultaggr;
5472 
5474  return FALSE;
5475 
5478  default:
5479  SCIPerrorMessage("wrong variable status\n");
5480  SCIPABORT();
5481  return FALSE; /*lint !e527 */
5482  }
5483 }
5484 
5485 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5486  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5487  * negated variable is created
5488  */
5490  SCIP_VAR* var, /**< problem variable to negate */
5491  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5492  SCIP_SET* set, /**< global SCIP settings */
5493  SCIP_STAT* stat, /**< problem statistics */
5494  SCIP_VAR** negvar /**< pointer to store the negated variable */
5495  )
5496 {
5497  assert(var != NULL);
5498  assert(var->scip == set->scip);
5499  assert(negvar != NULL);
5500 
5501  /* check, if we already created the negated variable */
5502  if( var->negatedvar == NULL )
5503  {
5504  char negvarname[SCIP_MAXSTRLEN];
5505 
5506  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5507 
5508  SCIPdebugMessage("creating negated variable of <%s>\n", var->name);
5509 
5510  /* negation is only possible for bounded variables */
5511  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5512  {
5513  SCIPerrorMessage("cannot negate unbounded variable\n");
5514  return SCIP_INVALIDDATA;
5515  }
5516 
5517  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5518 
5519  /* create negated variable */
5520  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5521  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5522  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5523  if( SCIPvarIsBinary(var) )
5524  (*negvar)->data.negate.constant = 1.0;
5525  else
5526  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5527 
5528  /* create event filter for transformed variable */
5529  if( SCIPvarIsTransformed(var) )
5530  {
5531  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5532  }
5533 
5534  /* set the bounds corresponding to the negation variable */
5535  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5536  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5537  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5538  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5539  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5540 
5541  /* link the variables together */
5542  var->negatedvar = *negvar;
5543  (*negvar)->negatedvar = var;
5544 
5545  /* mark both variables to be non-deletable */
5547  SCIPvarMarkNotDeletable(*negvar);
5548 
5549  /* copy the branch factor and priority, and use the negative preferred branching direction */
5550  (*negvar)->branchfactor = var->branchfactor;
5551  (*negvar)->branchpriority = var->branchpriority;
5552  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5553 
5554  /* copy doNotMultiaggr status */
5555  (*negvar)->donotmultaggr = var->donotmultaggr;
5556 
5557  /* copy lazy bounds (they have to be flipped) */
5558  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5559  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5560 
5561  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5562  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5563  assert((*negvar)->nuses == 1);
5564  }
5565  assert(var->negatedvar != NULL);
5566 
5567  /* return the negated variable */
5568  *negvar = var->negatedvar;
5569 
5570  /* exactly one variable of the negation pair has to be marked as negated variable */
5572 
5573  return SCIP_OKAY;
5574 }
5575 
5576 /** informs variable that its position in problem's vars array changed */
5577 static
5578 void varSetProbindex(
5579  SCIP_VAR* var, /**< problem variable */
5580  int probindex /**< new problem index of variable (-1 for removal) */
5581  )
5582 {
5583  assert(var != NULL);
5584  assert(probindex >= 0 || var->vlbs == NULL);
5585  assert(probindex >= 0 || var->vubs == NULL);
5586  assert(probindex >= 0 || var->implics == NULL);
5587 
5588  var->probindex = probindex;
5590  {
5591  assert(var->data.col != NULL);
5592  var->data.col->var_probindex = probindex;
5593  }
5594 }
5595 
5596 /** informs variable that its position in problem's vars array changed */
5597 void SCIPvarSetProbindex(
5598  SCIP_VAR* var, /**< problem variable */
5599  int probindex /**< new problem index of variable */
5600  )
5601 {
5602  assert(var != NULL);
5603  assert(probindex >= 0);
5604 
5605  varSetProbindex(var, probindex);
5606 }
5607 
5608 /** gives the variable a new name
5609  *
5610  * @note the old pointer is overwritten, which might result in a memory leakage
5611  */
5613  SCIP_VAR* var, /**< problem variable */
5614  const char* name /**< new name of variable */
5615  )
5616 {
5617  assert(var != NULL);
5618  assert(name != NULL);
5619 
5620  var->name = (char*)name;
5621 }
5622 
5623 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5624  * implication graph;
5625  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5626  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5627  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5628  * than removing the variables one by one, each time updating all lists of the other variables.
5629  */
5631  SCIP_VAR* var, /**< problem variable */
5632  BMS_BLKMEM* blkmem, /**< block memory buffer */
5633  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5634  SCIP_SET* set, /**< global SCIP settings */
5635  SCIP_Bool final /**< is this the final removal of all problem variables? */
5636  )
5637 {
5638  assert(SCIPvarGetProbindex(var) >= 0);
5639  assert(var->scip == set->scip);
5640 
5641  /* if the variable is active in the transformed problem, remove it from the implication graph */
5642  if( SCIPvarIsTransformed(var)
5644  {
5645  if( final )
5646  {
5647  /* just destroy the data structures */
5648  SCIPvboundsFree(&var->vlbs, blkmem);
5649  SCIPvboundsFree(&var->vubs, blkmem);
5650  SCIPimplicsFree(&var->implics, blkmem);
5651  }
5652  else
5653  {
5654  /* unlink the variable from all other variables' lists and free the data structures */
5655  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5656  }
5657  }
5658 
5659  /* mark the variable to be no longer a member of the problem */
5660  varSetProbindex(var, -1);
5661 
5662  return SCIP_OKAY;
5663 }
5664 
5665 /** marks the variable to be deleted from the problem */
5666 void SCIPvarMarkDeleted(
5667  SCIP_VAR* var /**< problem variable */
5668  )
5669 {
5670  assert(var != NULL);
5671  assert(var->probindex != -1);
5672 
5673  var->deleted = TRUE;
5674 }
5675 
5676 /** marks the variable to not to be multi-aggregated */
5678  SCIP_VAR* var /**< problem variable */
5679  )
5680 {
5681  SCIP_VAR* retvar;
5682 
5683  assert(var != NULL);
5684 
5685  retvar = varGetActiveVar(var);
5686  assert(retvar != NULL);
5687 
5688  switch( SCIPvarGetStatus(retvar) )
5689  {
5691  case SCIP_VARSTATUS_LOOSE:
5692  case SCIP_VARSTATUS_COLUMN:
5693  case SCIP_VARSTATUS_FIXED:
5694  retvar->donotmultaggr = TRUE;
5695  break;
5696 
5698  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5699  return SCIP_INVALIDDATA;
5700 
5703  default:
5704  SCIPerrorMessage("wrong variable status\n");
5705  return SCIP_INVALIDDATA;
5706  }
5707 
5708  return SCIP_OKAY;
5709 }
5710 
5711 /** changes type of variable; cannot be called, if var belongs to a problem */
5713  SCIP_VAR* var, /**< problem variable to change */
5714  SCIP_VARTYPE vartype /**< new type of variable */
5715  )
5716 {
5717  assert(var != NULL);
5718 
5719  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5720 
5721  if( var->probindex >= 0 )
5722  {
5723  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5724  return SCIP_INVALIDDATA;
5725  }
5726 
5727  var->vartype = vartype; /*lint !e641*/
5728  if( var->negatedvar != NULL )
5729  var->negatedvar->vartype = vartype; /*lint !e641*/
5730 
5731  return SCIP_OKAY;
5732 }
5733 
5734 /** appends OBJCHANGED event to the event queue */
5735 static
5737  SCIP_VAR* var, /**< problem variable to change */
5738  BMS_BLKMEM* blkmem, /**< block memory */
5739  SCIP_SET* set, /**< global SCIP settings */
5740  SCIP_PRIMAL* primal, /**< primal data */
5741  SCIP_LP* lp, /**< current LP data */
5742  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5743  SCIP_Real oldobj, /**< old objective value for variable */
5744  SCIP_Real newobj /**< new objective value for variable */
5745  )
5746 {
5747  SCIP_EVENT* event;
5748 
5749  assert(var != NULL);
5750  assert(var->scip == set->scip);
5751  assert(var->eventfilter != NULL);
5753  assert(SCIPvarIsTransformed(var));
5754  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5755 
5756  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5757  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5758 
5759  return SCIP_OKAY;
5760 }
5761 
5762 /** changes objective value of variable */
5764  SCIP_VAR* var, /**< variable to change */
5765  BMS_BLKMEM* blkmem, /**< block memory */
5766  SCIP_SET* set, /**< global SCIP settings */
5767  SCIP_PROB* prob, /**< problem data */
5768  SCIP_PRIMAL* primal, /**< primal data */
5769  SCIP_LP* lp, /**< current LP data */
5770  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5771  SCIP_Real newobj /**< new objective value for variable */
5772  )
5773 {
5774  SCIP_Real oldobj;
5775 
5776  assert(var != NULL);
5777  assert(set != NULL);
5778  assert(var->scip == set->scip);
5779 
5780  SCIPdebugMessage("changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5781 
5782  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5783  {
5784  switch( SCIPvarGetStatus(var) )
5785  {
5787  if( var->data.original.transvar != NULL )
5788  {
5789  /* @todo: shouldn't we take into account objsense and objfactor here? */
5790  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue, newobj) );
5791  }
5792  else
5793  {
5794  assert(set->stage == SCIP_STAGE_PROBLEM);
5795  var->obj = newobj;
5796  var->unchangedobj = newobj;
5797  }
5798  break;
5799 
5800  case SCIP_VARSTATUS_LOOSE:
5801  case SCIP_VARSTATUS_COLUMN:
5802  oldobj = var->obj;
5803  var->obj = newobj;
5804 
5805  /* update unchanged objective value of variable */
5806  if( !lp->divingobjchg )
5807  var->unchangedobj = newobj;
5808 
5809  /* update the number of variables with non-zero objective coefficient;
5810  * we only want to do the update, if the variable is added to the problem;
5811  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5812  */
5813  if( SCIPvarIsActive(var) )
5814  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
5815 
5816  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5817  break;
5818 
5819  case SCIP_VARSTATUS_FIXED:
5823  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
5824  return SCIP_INVALIDDATA;
5825 
5826  default:
5827  SCIPerrorMessage("unknown variable status\n");
5828  return SCIP_INVALIDDATA;
5829  }
5830  }
5831 
5832  return SCIP_OKAY;
5833 }
5834 
5835 /** adds value to objective value of variable */
5837  SCIP_VAR* var, /**< variable to change */
5838  BMS_BLKMEM* blkmem, /**< block memory */
5839  SCIP_SET* set, /**< global SCIP settings */
5840  SCIP_STAT* stat, /**< problem statistics */
5841  SCIP_PROB* transprob, /**< tranformed problem data */
5842  SCIP_PROB* origprob, /**< original problem data */
5843  SCIP_PRIMAL* primal, /**< primal data */
5844  SCIP_TREE* tree, /**< branch and bound tree */
5845  SCIP_REOPT* reopt, /**< reoptimization data structure */
5846  SCIP_LP* lp, /**< current LP data */
5847  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5848  SCIP_Real addobj /**< additional objective value for variable */
5849  )
5850 {
5851  assert(var != NULL);
5852  assert(set != NULL);
5853  assert(var->scip == set->scip);
5854  assert(set->stage < SCIP_STAGE_INITSOLVE);
5855 
5856  SCIPdebugMessage("adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
5857 
5858  if( !SCIPsetIsZero(set, addobj) )
5859  {
5860  SCIP_Real oldobj;
5861  int i;
5862 
5863  switch( SCIPvarGetStatus(var) )
5864  {
5866  if( var->data.original.transvar != NULL )
5867  {
5868  /* @todo: shouldn't we take into account objsense and objfactor here? */
5869  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5870  reopt, lp, eventqueue, addobj) );
5871  }
5872  else
5873  {
5874  assert(set->stage == SCIP_STAGE_PROBLEM);
5875  var->obj += addobj;
5876  var->unchangedobj += addobj;
5877  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5878  }
5879  break;
5880 
5881  case SCIP_VARSTATUS_LOOSE:
5882  case SCIP_VARSTATUS_COLUMN:
5883  oldobj = var->obj;
5884  var->obj += addobj;
5885 
5886  /* update unchanged objective value of variable */
5887  if( !lp->divingobjchg )
5888  {
5889  var->unchangedobj += addobj;
5890  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5891  }
5892 
5893  /* update the number of variables with non-zero objective coefficient;
5894  * we only want to do the update, if the variable is added to the problem;
5895  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5896  */
5897  if( SCIPvarIsActive(var) )
5898  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
5899 
5900  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5901  break;
5902 
5903  case SCIP_VARSTATUS_FIXED:
5904  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
5905  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
5906  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5907  break;
5908 
5910  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
5911  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
5912  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5913  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5914  lp, eventqueue, var->data.aggregate.scalar * addobj) );
5915  break;
5916 
5918  assert(!var->donotmultaggr);
5919  /* x = a_1*y_1 + ... + a_n*y_n + c -> add a_i*addobj to obj. val. of y_i, and c*addobj to obj. offset */
5920  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
5921  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5922  for( i = 0; i < var->data.multaggr.nvars; ++i )
5923  {
5924  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
5925  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
5926  }
5927  break;
5928 
5930  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
5931  assert(var->negatedvar != NULL);
5933  assert(var->negatedvar->negatedvar == var);
5934  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
5935  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5936  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5937  eventqueue, -addobj) );
5938  break;
5939 
5940  default:
5941  SCIPerrorMessage("unknown variable status\n");
5942  return SCIP_INVALIDDATA;
5943  }
5944  }
5945 
5946  return SCIP_OKAY;
5947 }
5948 
5949 /** changes objective value of variable in current dive */
5951  SCIP_VAR* var, /**< problem variable to change */
5952  SCIP_SET* set, /**< global SCIP settings */
5953  SCIP_LP* lp, /**< current LP data */
5954  SCIP_Real newobj /**< new objective value for variable */
5955  )
5956 {
5957  assert(var != NULL);
5958  assert(set != NULL);
5959  assert(var->scip == set->scip);
5960  assert(lp != NULL);
5961 
5962  SCIPdebugMessage("changing objective of <%s> to %g in current dive\n", var->name, newobj);
5963 
5964  if( SCIPsetIsZero(set, newobj) )
5965  newobj = 0.0;
5966 
5967  /* change objective value of attached variables */
5968  switch( SCIPvarGetStatus(var) )
5969  {
5971  assert(var->data.original.transvar != NULL);
5972  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
5973  break;
5974 
5975  case SCIP_VARSTATUS_COLUMN:
5976  assert(var->data.col != NULL);
5977  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
5978  break;
5979 
5980  case SCIP_VARSTATUS_LOOSE:
5981  case SCIP_VARSTATUS_FIXED:
5982  /* nothing to do here: only the constant shift in objective function would change */
5983  break;
5984 
5985  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
5986  assert(var->data.aggregate.var != NULL);
5987  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
5988  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
5989  /* the constant can be ignored, because it would only affect the objective shift */
5990  break;
5991 
5993  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
5994  return SCIP_INVALIDDATA;
5995 
5996  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
5997  assert(var->negatedvar != NULL);
5999  assert(var->negatedvar->negatedvar == var);
6000  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6001  /* the offset can be ignored, because it would only affect the objective shift */
6002  break;
6003 
6004  default:
6005  SCIPerrorMessage("unknown variable status\n");
6006  return SCIP_INVALIDDATA;
6007  }
6008 
6009  return SCIP_OKAY;
6010 }
6011 
6012 /** adjust lower bound to integral value, if variable is integral */
6013 void SCIPvarAdjustLb(
6014  SCIP_VAR* var, /**< problem variable */
6015  SCIP_SET* set, /**< global SCIP settings */
6016  SCIP_Real* lb /**< pointer to lower bound to adjust */
6017  )
6018 {
6019  assert(var != NULL);
6020  assert(set != NULL);
6021  assert(var->scip == set->scip);
6022  assert(lb != NULL);
6023 
6024  SCIPdebugMessage("adjust lower bound %g of <%s>\n", *lb, var->name);
6025 
6026  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6027 }
6028 
6029 /** adjust upper bound to integral value, if variable is integral */
6030 void SCIPvarAdjustUb(
6031  SCIP_VAR* var, /**< problem variable */
6032  SCIP_SET* set, /**< global SCIP settings */
6033  SCIP_Real* ub /**< pointer to upper bound to adjust */
6034  )
6035 {
6036  assert(var != NULL);
6037  assert(set != NULL);
6038  assert(var->scip == set->scip);
6039  assert(ub != NULL);
6040 
6041  SCIPdebugMessage("adjust upper bound %g of <%s>\n", *ub, var->name);
6042 
6043  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6044 }
6045 
6046 /** adjust lower or upper bound to integral value, if variable is integral */
6047 void SCIPvarAdjustBd(
6048  SCIP_VAR* var, /**< problem variable */
6049  SCIP_SET* set, /**< global SCIP settings */
6050  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6051  SCIP_Real* bd /**< pointer to bound to adjust */
6052  )
6053 {
6054  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6055 
6056  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6057  SCIPvarAdjustLb(var, set, bd);
6058  else
6059  SCIPvarAdjustUb(var, set, bd);
6060 }
6061 
6062 /** changes lower bound of original variable in original problem */
6064  SCIP_VAR* var, /**< problem variable to change */
6065  SCIP_SET* set, /**< global SCIP settings */
6066  SCIP_Real newbound /**< new bound for variable */
6067  )
6068 {
6069  int i;
6070 
6071  assert(var != NULL);
6072  assert(!SCIPvarIsTransformed(var));
6074  assert(set != NULL);
6075  assert(var->scip == set->scip);
6076  assert(set->stage == SCIP_STAGE_PROBLEM);
6077 
6078  /* check that the bound is feasible */
6079  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6080  /* adjust bound to integral value if variable is of integral type */
6081  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6082 
6083  if( SCIPsetIsZero(set, newbound) )
6084  newbound = 0.0;
6085 
6086  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6088  {
6089  SCIPdebugMessage("changing original lower bound of <%s> from %g to %g\n",
6090  var->name, var->data.original.origdom.lb, newbound);
6091 
6092  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6093  return SCIP_OKAY;
6094 
6095  /* change the bound */
6096  var->data.original.origdom.lb = newbound;
6097  }
6098  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6099  {
6100  assert( var->negatedvar != NULL );
6101  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6102  }
6103 
6104  /* process parent variables */
6105  for( i = 0; i < var->nparentvars; ++i )
6106  {
6107  SCIP_VAR* parentvar;
6108 
6109  parentvar = var->parentvars[i];
6110  assert(parentvar != NULL);
6111  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6112  assert(parentvar->negatedvar == var);
6113  assert(var->negatedvar == parentvar);
6114 
6115  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6116  }
6117 
6118  return SCIP_OKAY;
6119 }
6120 
6121 /** changes upper bound of original variable in original problem */
6123  SCIP_VAR* var, /**< problem variable to change */
6124  SCIP_SET* set, /**< global SCIP settings */
6125  SCIP_Real newbound /**< new bound for variable */
6126  )
6127 {
6128  int i;
6129 
6130  assert(var != NULL);
6131  assert(!SCIPvarIsTransformed(var));
6133  assert(set != NULL);
6134  assert(var->scip == set->scip);
6135  assert(set->stage == SCIP_STAGE_PROBLEM);
6136 
6137  /* check that the bound is feasible */
6138  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6139  /* adjust bound to integral value if variable is of integral type */
6140  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6141 
6142  if( SCIPsetIsZero(set, newbound) )
6143  newbound = 0.0;
6144 
6145  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6147  {
6148  SCIPdebugMessage("changing original upper bound of <%s> from %g to %g\n",
6149  var->name, var->data.original.origdom.ub, newbound);
6150 
6151  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6152  return SCIP_OKAY;
6153 
6154  /* change the bound */
6155  var->data.original.origdom.ub = newbound;
6156  }
6157  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6158  {
6159  assert( var->negatedvar != NULL );
6160  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6161  }
6162 
6163  /* process parent variables */
6164  for( i = 0; i < var->nparentvars; ++i )
6165  {
6166  SCIP_VAR* parentvar;
6167 
6168  parentvar = var->parentvars[i];
6169  assert(parentvar != NULL);
6170  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6171  assert(parentvar->negatedvar == var);
6172  assert(var->negatedvar == parentvar);
6173 
6174  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6175  }
6176 
6177  return SCIP_OKAY;
6178 }
6179 
6180 /** appends GLBCHANGED event to the event queue */
6181 static
6183  SCIP_VAR* var, /**< problem variable to change */
6184  BMS_BLKMEM* blkmem, /**< block memory */
6185  SCIP_SET* set, /**< global SCIP settings */
6186  SCIP_LP* lp, /**< current LP data */
6187  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6188  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6189  SCIP_Real oldbound, /**< old lower bound for variable */
6190  SCIP_Real newbound /**< new lower bound for variable */
6191  )
6192 {
6193  assert(var != NULL);
6194  assert(var->eventfilter != NULL);
6195  assert(SCIPvarIsTransformed(var));
6196  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6197  assert(set != NULL);
6198  assert(var->scip == set->scip);
6199 
6200  /* check, if the variable is being tracked for bound changes
6201  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6202  */
6203  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6206  {
6207  SCIP_EVENT* event;
6208 
6209  SCIPdebugMessage("issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6210 
6211  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6212  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6213  }
6214 
6215  return SCIP_OKAY;
6216 }
6217 
6218 /** appends GUBCHANGED event to the event queue */
6219 static
6221  SCIP_VAR* var, /**< problem variable to change */
6222  BMS_BLKMEM* blkmem, /**< block memory */
6223  SCIP_SET* set, /**< global SCIP settings */
6224  SCIP_LP* lp, /**< current LP data */
6225  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6226  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6227  SCIP_Real oldbound, /**< old lower bound for variable */
6228  SCIP_Real newbound /**< new lower bound for variable */
6229  )
6230 {
6231  assert(var != NULL);
6232  assert(var->eventfilter != NULL);
6233  assert(SCIPvarIsTransformed(var));
6234  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6235  assert(set != NULL);
6236  assert(var->scip == set->scip);
6237 
6238  /* check, if the variable is being tracked for bound changes
6239  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6240  */
6241  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6244  {
6245  SCIP_EVENT* event;
6246 
6247  SCIPdebugMessage("issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6248 
6249  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6250  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6251  }
6252 
6253  return SCIP_OKAY;
6254 }
6255 
6256 /** appends GHOLEADDED event to the event queue */
6257 static
6259  SCIP_VAR* var, /**< problem variable to change */
6260  BMS_BLKMEM* blkmem, /**< block memory */
6261  SCIP_SET* set, /**< global SCIP settings */
6262  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6263  SCIP_Real left, /**< left bound of open interval in new hole */
6264  SCIP_Real right /**< right bound of open interval in new hole */
6265  )
6266 {
6267  assert(var != NULL);
6268  assert(var->eventfilter != NULL);
6269  assert(SCIPvarIsTransformed(var));
6270  assert(set != NULL);
6271  assert(var->scip == set->scip);
6272  assert(SCIPsetIsLT(set, left, right));
6273 
6274  /* check, if the variable is being tracked for bound changes */
6275  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6276  {
6277  SCIP_EVENT* event;
6278 
6279  SCIPdebugMessage("issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6280 
6281  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6282  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6283  }
6284 
6285  return SCIP_OKAY;
6286 }
6287 
6288 /** increases root bound change statistics after a global bound change */
6289 static
6290 void varIncRootboundchgs(
6291  SCIP_VAR* var, /**< problem variable to change */
6292  SCIP_SET* set, /**< global SCIP settings */
6293  SCIP_STAT* stat /**< problem statistics */
6294  )
6295 {
6296  assert(var != NULL);
6297  assert(set != NULL);
6298  assert(var->scip == set->scip);
6299  assert(stat != NULL);
6300 
6301  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6302  {
6303  stat->nrootboundchgs++;
6304  stat->nrootboundchgsrun++;
6305  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6306  {
6307  stat->nrootintfixings++;
6308  stat->nrootintfixingsrun++;
6309  }
6310  }
6311 }
6312 
6313 /* forward declaration, because both methods call each other recursively */
6314 
6315 /* performs the current change in upper bound, changes all parents accordingly */
6316 static
6318  SCIP_VAR* var, /**< problem variable to change */
6319  BMS_BLKMEM* blkmem, /**< block memory */
6320  SCIP_SET* set, /**< global SCIP settings */
6321  SCIP_STAT* stat, /**< problem statistics */
6322  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6323  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6324  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6325  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6326  SCIP_Real newbound /**< new bound for variable */
6327  );
6328 
6329 /** performs the current change in lower bound, changes all parents accordingly */
6330 static
6332  SCIP_VAR* var, /**< problem variable to change */
6333  BMS_BLKMEM* blkmem, /**< block memory */
6334  SCIP_SET* set, /**< global SCIP settings */
6335  SCIP_STAT* stat, /**< problem statistics */
6336  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6337  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6338  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6339  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6340  SCIP_Real newbound /**< new bound for variable */
6341  )
6342 {
6343  SCIP_VAR* parentvar;
6344  SCIP_Real oldbound;
6345  int i;
6346 
6347  assert(var != NULL);
6348  /* local domains can violate global bounds but not more than feasibility epsilon */
6349  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6350  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6351  assert(blkmem != NULL);
6352  assert(set != NULL);
6353  assert(var->scip == set->scip);
6354  assert(stat != NULL);
6355 
6356  /* adjust bound to integral value if variable is of integral type */
6357  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6358 
6359  /* check that the bound is feasible */
6360  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6361  {
6362  /* due to numerics we only want to be feasible in feasibility tolerance */
6363  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6364  newbound = var->glbdom.ub;
6365  }
6366  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6367 
6368  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6369 
6370  SCIPdebugMessage("process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6371 
6372  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6373  return SCIP_OKAY;
6374 
6375  /* check bound on debugging solution */
6376  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6377 
6378  /* change the bound */
6379  oldbound = var->glbdom.lb;
6380  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6381  var->glbdom.lb = newbound;
6382  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6383  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6384 
6385  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6386  {
6387  /* merges overlapping holes into single holes, moves bounds respectively */
6388  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6389  }
6390 
6391  /* update the root bound changes counters */
6392  varIncRootboundchgs(var, set, stat);
6393 
6394  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6395  * redundant bound changes to be branching decisions
6396  */
6397  for( i = 0; i < var->nlbchginfos; ++i )
6398  {
6399  assert(var->lbchginfos[i].var == var);
6400 
6401  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6402  {
6403  SCIPdebugMessage(" -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6404  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6405  var->lbchginfos[i].oldbound = var->glbdom.lb;
6406  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6407  {
6408  /* this bound change is redundant due to the new global bound */
6409  var->lbchginfos[i].newbound = var->glbdom.lb;
6410  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6411  var->lbchginfos[i].redundant = TRUE;
6412  }
6413  else
6414  break; /* from now on, the remaining local bound changes are not redundant */
6415  }
6416  else
6417  break; /* from now on, the remaining local bound changes are not redundant */
6418  }
6419 
6420  /* remove redundant implications and variable bounds */
6422  {
6423  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6424  }
6425 
6426  /* issue bound change event */
6427  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6428  if( var->eventfilter != NULL )
6429  {
6430  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6431  }
6432 
6433  /* process parent variables */
6434  for( i = 0; i < var->nparentvars; ++i )
6435  {
6436  parentvar = var->parentvars[i];
6437  assert(parentvar != NULL);
6438 
6439  switch( SCIPvarGetStatus(parentvar) )
6440  {
6442  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6443  break;
6444 
6445  case SCIP_VARSTATUS_COLUMN:
6446  case SCIP_VARSTATUS_LOOSE:
6447  case SCIP_VARSTATUS_FIXED:
6449  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6450  return SCIP_INVALIDDATA;
6451 
6452  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6453  assert(parentvar->data.aggregate.var == var);
6454  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6455  {
6456  SCIP_Real parentnewbound;
6457 
6458  /* a > 0 -> change lower bound of y */
6459  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, -oldbound))
6460  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6461  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6462 
6463  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6464  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6465  else
6466  parentnewbound = newbound;
6467  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6468  }
6469  else
6470  {
6471  SCIP_Real parentnewbound;
6472 
6473  /* a < 0 -> change upper bound of y */
6474  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6475  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, -oldbound))
6476  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6477  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6478 
6479  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6480  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6481  else
6482  parentnewbound = -newbound;
6483  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6484  }
6485  break;
6486 
6487  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6488  assert(parentvar->negatedvar != NULL);
6489  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6490  assert(parentvar->negatedvar->negatedvar == parentvar);
6491  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6492  parentvar->data.negate.constant - newbound) );
6493  break;
6494 
6495  default:
6496  SCIPerrorMessage("unknown variable status\n");
6497  return SCIP_INVALIDDATA;
6498  }
6499  }
6500 
6501  return SCIP_OKAY;
6502 }
6503 
6504 /** performs the current change in upper bound, changes all parents accordingly */
6505 static
6507  SCIP_VAR* var, /**< problem variable to change */
6508  BMS_BLKMEM* blkmem, /**< block memory */
6509  SCIP_SET* set, /**< global SCIP settings */
6510  SCIP_STAT* stat, /**< problem statistics */
6511  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6512  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6513  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6514  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6515  SCIP_Real newbound /**< new bound for variable */
6516  )
6517 {
6518  SCIP_VAR* parentvar;
6519  SCIP_Real oldbound;
6520  int i;
6521 
6522  assert(var != NULL);
6523  /* local domains can violate global bounds but not more than feasibility epsilon */
6524  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6525  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6526  assert(blkmem != NULL);
6527  assert(set != NULL);
6528  assert(var->scip == set->scip);
6529  assert(stat != NULL);
6530 
6531  /* adjust bound to integral value if variable is of integral type */
6532  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6533 
6534  /* check that the bound is feasible */
6535  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6536  {
6537  /* due to numerics we only want to be feasible in feasibility tolerance */
6538  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6539  newbound = var->glbdom.lb;
6540  }
6541  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6542 
6543  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6544 
6545  SCIPdebugMessage("process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6546 
6547  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6548  return SCIP_OKAY;
6549 
6550  /* check bound on debugging solution */
6551  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6552 
6553  /* change the bound */
6554  oldbound = var->glbdom.ub;
6555  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6556  var->glbdom.ub = newbound;
6557  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6558  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6559 
6560  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6561  {
6562  /* merges overlapping holes into single holes, moves bounds respectively */
6563  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6564  }
6565 
6566  /* update the root bound changes counters */
6567  varIncRootboundchgs(var, set, stat);
6568 
6569  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6570  * redundant bound changes to be branching decisions
6571  */
6572  for( i = 0; i < var->nubchginfos; ++i )
6573  {
6574  assert(var->ubchginfos[i].var == var);
6575  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6576  {
6577  SCIPdebugMessage(" -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6578  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6579  var->ubchginfos[i].oldbound = var->glbdom.ub;
6580  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6581  {
6582  /* this bound change is redundant due to the new global bound */
6583  var->ubchginfos[i].newbound = var->glbdom.ub;
6584  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6585  var->ubchginfos[i].redundant = TRUE;
6586  }
6587  else
6588  break; /* from now on, the remaining local bound changes are not redundant */
6589  }
6590  else
6591  break; /* from now on, the remaining local bound changes are not redundant */
6592  }
6593 
6594  /* remove redundant implications and variable bounds */
6596  {
6597  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6598  }
6599 
6600  /* issue bound change event */
6601  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6602  if( var->eventfilter != NULL )
6603  {
6604  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6605  }
6606 
6607  /* process parent variables */
6608  for( i = 0; i < var->nparentvars; ++i )
6609  {
6610  parentvar = var->parentvars[i];
6611  assert(parentvar != NULL);
6612 
6613  switch( SCIPvarGetStatus(parentvar) )
6614  {
6616  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6617  break;
6618 
6619  case SCIP_VARSTATUS_COLUMN:
6620  case SCIP_VARSTATUS_LOOSE:
6621  case SCIP_VARSTATUS_FIXED:
6623  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6624  return SCIP_INVALIDDATA;
6625 
6626  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6627  assert(parentvar->data.aggregate.var == var);
6628  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6629  {
6630  SCIP_Real parentnewbound;
6631 
6632  /* a > 0 -> change upper bound of y */
6633  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, oldbound))
6634  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6635  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6636  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6637  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6638  else
6639  parentnewbound = newbound;
6640  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6641  }
6642  else
6643  {
6644  SCIP_Real parentnewbound;
6645 
6646  /* a < 0 -> change lower bound of y */
6647  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6648  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, oldbound))
6649  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6650  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6651  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6652  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6653  else
6654  parentnewbound = -newbound;
6655  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6656  }
6657  break;
6658 
6659  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6660  assert(parentvar->negatedvar != NULL);
6661  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6662  assert(parentvar->negatedvar->negatedvar == parentvar);
6663  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6664  parentvar->data.negate.constant - newbound) );
6665  break;
6666 
6667  default:
6668  SCIPerrorMessage("unknown variable status\n");
6669  return SCIP_INVALIDDATA;
6670  }
6671  }
6672 
6673  return SCIP_OKAY;
6674 }
6675 
6676 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6677  * updates local lower bound if the global bound is tighter
6678  */
6680  SCIP_VAR* var, /**< problem variable to change */
6681  BMS_BLKMEM* blkmem, /**< block memory */
6682  SCIP_SET* set, /**< global SCIP settings */
6683  SCIP_STAT* stat, /**< problem statistics */
6684  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6685  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6686  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6687  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6688  SCIP_Real newbound /**< new bound for variable */
6689  )
6690 {
6691  assert(var != NULL);
6692  assert(blkmem != NULL);
6693  assert(set != NULL);
6694  assert(var->scip == set->scip);
6695 
6696  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6697  * of the domain within feastol
6698  */
6699  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6700 
6701  /* adjust bound to integral value if variable is of integral type */
6702  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6703 
6704  /* check that the adjusted bound is feasible
6705  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6706  * here because we reset bounds to their original value!
6707  */
6708  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6709 
6710  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6711  {
6712  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6713  newbound = MIN(newbound, var->glbdom.ub);
6714  }
6715  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6716 
6717  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6718  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6719  */
6720  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound));
6721 
6722  SCIPdebugMessage("changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6723 
6724  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6725  return SCIP_OKAY;
6726 
6727  /* change bounds of attached variables */
6728  switch( SCIPvarGetStatus(var) )
6729  {
6731  if( var->data.original.transvar != NULL )
6732  {
6733  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6734  cliquetable, newbound) );
6735  }
6736  else
6737  {
6738  assert(set->stage == SCIP_STAGE_PROBLEM);
6739  if( newbound > SCIPvarGetLbLocal(var) )
6740  {
6741  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6742  }
6743  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6744  }
6745  break;
6746 
6747  case SCIP_VARSTATUS_COLUMN:
6748  case SCIP_VARSTATUS_LOOSE:
6749  if( newbound > SCIPvarGetLbLocal(var) )
6750  {
6751  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6752  }
6753  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6754  break;
6755 
6756  case SCIP_VARSTATUS_FIXED:
6757  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6758  return SCIP_INVALIDDATA;
6759 
6760  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6761  assert(var->data.aggregate.var != NULL);
6762  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6763  {
6764  SCIP_Real childnewbound;
6765 
6766  /* a > 0 -> change lower bound of y */
6767  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6768  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6770  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6771  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6772  else
6773  childnewbound = newbound;
6774  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6775  childnewbound) );
6776  }
6777  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6778  {
6779  SCIP_Real childnewbound;
6780 
6781  /* a < 0 -> change upper bound of y */
6782  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6783  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6785  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6786  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6787  else
6788  childnewbound = -newbound;
6789  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6790  childnewbound) );
6791  }
6792  else
6793  {
6794  SCIPerrorMessage("scalar is zero in aggregation\n");
6795  return SCIP_INVALIDDATA;
6796  }
6797  break;
6798 
6800  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6801  return SCIP_INVALIDDATA;
6802 
6803  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6804  assert(var->negatedvar != NULL);
6806  assert(var->negatedvar->negatedvar == var);
6807  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6808  var->data.negate.constant - newbound) );
6809  break;
6810 
6811  default:
6812  SCIPerrorMessage("unknown variable status\n");
6813  return SCIP_INVALIDDATA;
6814  }
6815 
6816  return SCIP_OKAY;
6817 }
6818 
6819 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
6820  * updates local upper bound if the global bound is tighter
6821  */
6823  SCIP_VAR* var, /**< problem variable to change */
6824  BMS_BLKMEM* blkmem, /**< block memory */
6825  SCIP_SET* set, /**< global SCIP settings */
6826  SCIP_STAT* stat, /**< problem statistics */
6827  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6828  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6829  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6830  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6831  SCIP_Real newbound /**< new bound for variable */
6832  )
6833 {
6834  assert(var != NULL);
6835  assert(blkmem != NULL);
6836  assert(set != NULL);
6837  assert(var->scip == set->scip);
6838 
6839  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6840  * of the domain within feastol
6841  */
6842  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6843 
6844  /* adjust bound to integral value if variable is of integral type */
6845  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6846 
6847  /* check that the adjusted bound is feasible
6848  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6849  * here because we reset bounds to their original value!
6850  */
6851  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6852 
6853  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6854  {
6855  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
6856  newbound = MAX(newbound, var->glbdom.lb);
6857  }
6858  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6859 
6860  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6861  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6862  */
6863  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound));
6864 
6865  SCIPdebugMessage("changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
6866 
6867  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
6868  return SCIP_OKAY;
6869 
6870  /* change bounds of attached variables */
6871  switch( SCIPvarGetStatus(var) )
6872  {
6874  if( var->data.original.transvar != NULL )
6875  {
6876  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6877  newbound) );
6878  }
6879  else
6880  {
6881  assert(set->stage == SCIP_STAGE_PROBLEM);
6882  if( newbound < SCIPvarGetUbLocal(var) )
6883  {
6884  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6885  }
6886  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6887  }
6888  break;
6889 
6890  case SCIP_VARSTATUS_COLUMN:
6891  case SCIP_VARSTATUS_LOOSE:
6892  if( newbound < SCIPvarGetUbLocal(var) )
6893  {
6894  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6895  }
6896  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6897  break;
6898 
6899  case SCIP_VARSTATUS_FIXED:
6900  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6901  return SCIP_INVALIDDATA;
6902 
6903  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6904  assert(var->data.aggregate.var != NULL);
6905  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6906  {
6907  SCIP_Real childnewbound;
6908 
6909  /* a > 0 -> change lower bound of y */
6910  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6911  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6913  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6914  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6915  else
6916  childnewbound = newbound;
6917  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6918  childnewbound) );
6919  }
6920  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6921  {
6922  SCIP_Real childnewbound;
6923 
6924  /* a < 0 -> change upper bound of y */
6925  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6926  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6928  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6929  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6930  else
6931  childnewbound = -newbound;
6932  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6933  childnewbound) );
6934  }
6935  else
6936  {
6937  SCIPerrorMessage("scalar is zero in aggregation\n");
6938  return SCIP_INVALIDDATA;
6939  }
6940  break;
6941 
6943  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6944  return SCIP_INVALIDDATA;
6945 
6946  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6947  assert(var->negatedvar != NULL);
6949  assert(var->negatedvar->negatedvar == var);
6950  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6951  var->data.negate.constant - newbound) );
6952  break;
6953 
6954  default:
6955  SCIPerrorMessage("unknown variable status\n");
6956  return SCIP_INVALIDDATA;
6957  }
6958 
6959  return SCIP_OKAY;
6960 }
6961 
6962 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
6964  SCIP_VAR* var, /**< problem variable */
6965  SCIP_SET* set, /**< global SCIP settings */
6966  SCIP_Real lazylb /**< the lazy lower bound to be set */
6967  )
6968 {
6969  assert(var != NULL);
6970  assert(var->probindex != -1);
6971  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
6972  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
6973  assert(set != NULL);
6974  assert(var->scip == set->scip);
6975 
6976  /* variable should not be in the LP */
6978  return SCIP_INVALIDCALL;
6979 
6980  var->lazylb = lazylb;
6981 
6982  return SCIP_OKAY;
6983 }
6984 
6985 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
6987  SCIP_VAR* var, /**< problem variable */
6988  SCIP_SET* set, /**< global SCIP settings */
6989  SCIP_Real lazyub /**< the lazy lower bound to be set */
6990  )
6991 {
6992  assert(var != NULL);
6993  assert(var->probindex != -1);
6994  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
6995  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
6996  assert(set != NULL);
6997  assert(var->scip == set->scip);
6998 
6999  /* variable should not be in the LP */
7001  return SCIP_INVALIDCALL;
7002 
7003  var->lazyub = lazyub;
7004 
7005  return SCIP_OKAY;
7006 }
7007 
7008 
7009 /** changes global bound of variable; if possible, adjusts bound to integral value;
7010  * updates local bound if the global bound is tighter
7011  */
7013  SCIP_VAR* var, /**< problem variable to change */
7014  BMS_BLKMEM* blkmem, /**< block memory */
7015  SCIP_SET* set, /**< global SCIP settings */
7016  SCIP_STAT* stat, /**< problem statistics */
7017  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7018  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7019  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7020  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7021  SCIP_Real newbound, /**< new bound for variable */
7022  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7023  )
7024 {
7025  /* apply bound change to the LP data */
7026  switch( boundtype )
7027  {
7028  case SCIP_BOUNDTYPE_LOWER:
7029  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7030  case SCIP_BOUNDTYPE_UPPER:
7031  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7032  default:
7033  SCIPerrorMessage("unknown bound type\n");
7034  return SCIP_INVALIDDATA;
7035  }
7036 }
7037 
7038 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7039 static
7041  SCIP_VAR* var, /**< problem variable to change */
7042  BMS_BLKMEM* blkmem, /**< block memory */
7043  SCIP_SET* set, /**< global SCIP settings */
7044  SCIP_LP* lp, /**< current LP data */
7045  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7046  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7047  SCIP_Real oldbound, /**< old lower bound for variable */
7048  SCIP_Real newbound /**< new lower bound for variable */
7049  )
7050 {
7051  assert(var != NULL);
7052  assert(var->eventfilter != NULL);
7053  assert(SCIPvarIsTransformed(var));
7054  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7055  assert(set != NULL);
7056  assert(var->scip == set->scip);
7057 
7058  /* check, if the variable is being tracked for bound changes
7059  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7060  */
7061  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7064  {
7065  SCIP_EVENT* event;
7066 
7067  SCIPdebugMessage("issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7068 
7069  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7070  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7071  }
7072 
7073  return SCIP_OKAY;
7074 }
7075 
7076 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7077 static
7079  SCIP_VAR* var, /**< problem variable to change */
7080  BMS_BLKMEM* blkmem, /**< block memory */
7081  SCIP_SET* set, /**< global SCIP settings */
7082  SCIP_LP* lp, /**< current LP data */
7083  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7084  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7085  SCIP_Real oldbound, /**< old upper bound for variable */
7086  SCIP_Real newbound /**< new upper bound for variable */
7087  )
7088 {
7089  assert(var != NULL);
7090  assert(var->eventfilter != NULL);
7091  assert(SCIPvarIsTransformed(var));
7092  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7093  assert(set != NULL);
7094  assert(var->scip == set->scip);
7095 
7096  /* check, if the variable is being tracked for bound changes
7097  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7098  */
7099  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7102  {
7103  SCIP_EVENT* event;
7104 
7105  SCIPdebugMessage("issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7106 
7107  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7108  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7109  }
7110 
7111  return SCIP_OKAY;
7112 }
7113 
7114 /* forward declaration, because both methods call each other recursively */
7115 
7116 /* performs the current change in upper bound, changes all parents accordingly */
7117 static
7119  SCIP_VAR* var, /**< problem variable to change */
7120  BMS_BLKMEM* blkmem, /**< block memory */
7121  SCIP_SET* set, /**< global SCIP settings */
7122  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7123  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7124  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7125  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7126  SCIP_Real newbound /**< new bound for variable */
7127  );
7128 
7129 /** performs the current change in lower bound, changes all parents accordingly */
7130 static
7132  SCIP_VAR* var, /**< problem variable to change */
7133  BMS_BLKMEM* blkmem, /**< block memory */
7134  SCIP_SET* set, /**< global SCIP settings */
7135  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7136  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7137  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7138  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7139  SCIP_Real newbound /**< new bound for variable */
7140  )
7141 {
7142  SCIP_VAR* parentvar;
7143  SCIP_Real oldbound;
7144  int i;
7145 
7146  assert(var != NULL);
7147  assert(set != NULL);
7148  assert(var->scip == set->scip);
7149  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7150  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7152 
7153  /* check that the bound is feasible */
7154  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7155  /* adjust bound to integral value if variable is of integral type */
7156  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7157 
7158  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7159  {
7160  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7161  newbound = MIN(newbound, var->locdom.ub);
7162  }
7163  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7164 
7165  SCIPdebugMessage("process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7166 
7167  if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7168  return SCIP_OKAY;
7169  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
7170  newbound = var->glbdom.lb;
7171 
7172  /* change the bound */
7173  oldbound = var->locdom.lb;
7174  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7175  var->locdom.lb = newbound;
7176 
7177  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7178  * once update the statistic
7179  */
7180  if( stat != NULL )
7181  stat->domchgcount++;
7182 
7183  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7184  {
7185  /* merges overlapping holes into single holes, moves bounds respectively */
7186  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7187  }
7188 
7189  /* issue bound change event */
7190  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7191  if( var->eventfilter != NULL )
7192  {
7193  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7194  }
7195 
7196  /* process parent variables */
7197  for( i = 0; i < var->nparentvars; ++i )
7198  {
7199  parentvar = var->parentvars[i];
7200  assert(parentvar != NULL);
7201 
7202  switch( SCIPvarGetStatus(parentvar) )
7203  {
7205  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7206  break;
7207 
7208  case SCIP_VARSTATUS_COLUMN:
7209  case SCIP_VARSTATUS_LOOSE:
7210  case SCIP_VARSTATUS_FIXED:
7212  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7213  return SCIP_INVALIDDATA;
7214 
7215  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7216  assert(parentvar->data.aggregate.var == var);
7217  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7218  {
7219  SCIP_Real parentnewbound;
7220 
7221  /* a > 0 -> change lower bound of y */
7222  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, -oldbound))
7223  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7224  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7225 
7226  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7227  {
7228  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7229  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7230  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7231  * as a result, the parent's lower bound is set to it's upper bound, and not above
7232  */
7233  if( parentnewbound > parentvar->glbdom.ub )
7234  {
7235  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7236  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7237  parentnewbound = parentvar->glbdom.ub;
7238  }
7239  }
7240  else
7241  parentnewbound = newbound;
7242  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7243  }
7244  else
7245  {
7246  SCIP_Real parentnewbound;
7247 
7248  /* a < 0 -> change upper bound of y */
7249  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7250  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, -oldbound))
7251  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7252  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7253 
7254  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7255  {
7256  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7257  /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7258  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7259  * as a result, the parent's upper bound is set to it's lower bound, and not below
7260  */
7261  if( parentnewbound < parentvar->glbdom.lb )
7262  {
7263  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7264  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7265  parentnewbound = parentvar->glbdom.lb;
7266  }
7267  }
7268  else
7269  parentnewbound = -newbound;
7270  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7271  }
7272  break;
7273 
7274  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7275  assert(parentvar->negatedvar != NULL);
7276  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7277  assert(parentvar->negatedvar->negatedvar == parentvar);
7278  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7279  parentvar->data.negate.constant - newbound) );
7280  break;
7281 
7282  default:
7283  SCIPerrorMessage("unknown variable status\n");
7284  return SCIP_INVALIDDATA;
7285  }
7286  }
7287 
7288  return SCIP_OKAY;
7289 }
7290 
7291 /** performs the current change in upper bound, changes all parents accordingly */
7292 static
7294  SCIP_VAR* var, /**< problem variable to change */
7295  BMS_BLKMEM* blkmem, /**< block memory */
7296  SCIP_SET* set, /**< global SCIP settings */
7297  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7298  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7299  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7300  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7301  SCIP_Real newbound /**< new bound for variable */
7302  )
7303 {
7304  SCIP_VAR* parentvar;
7305  SCIP_Real oldbound;
7306  int i;
7307 
7308  assert(var != NULL);
7309  assert(set != NULL);
7310  assert(var->scip == set->scip);
7311  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7312  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7314 
7315  /* check that the bound is feasible */
7316  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7317  /* adjust bound to integral value if variable is of integral type */
7318  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7319 
7320  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7321  {
7322  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7323  newbound = MAX(newbound, var->locdom.lb);
7324  }
7325  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7326 
7327  SCIPdebugMessage("process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7328 
7329  if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7330  return SCIP_OKAY;
7331  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
7332  newbound = var->glbdom.ub;
7333 
7334  /* change the bound */
7335  oldbound = var->locdom.ub;
7336  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7337  var->locdom.ub = newbound;
7338 
7339  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7340  * once update the statistic
7341  */
7342  if( stat != NULL )
7343  stat->domchgcount++;
7344 
7345  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7346  {
7347  /* merges overlapping holes into single holes, moves bounds respectively */
7348  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7349  }
7350 
7351  /* issue bound change event */
7352  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7353  if( var->eventfilter != NULL )
7354  {
7355  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7356  }
7357 
7358  /* process parent variables */
7359  for( i = 0; i < var->nparentvars; ++i )
7360  {
7361  parentvar = var->parentvars[i];
7362  assert(parentvar != NULL);
7363 
7364  switch( SCIPvarGetStatus(parentvar) )
7365  {
7367  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7368  break;
7369 
7370  case SCIP_VARSTATUS_COLUMN:
7371  case SCIP_VARSTATUS_LOOSE:
7372  case SCIP_VARSTATUS_FIXED:
7374  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7375  return SCIP_INVALIDDATA;
7376 
7377  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7378  assert(parentvar->data.aggregate.var == var);
7379  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7380  {
7381  SCIP_Real parentnewbound;
7382 
7383  /* a > 0 -> change upper bound of x */
7384  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, oldbound))
7385  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7386  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7387  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7388  {
7389  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7390  /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7391  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7392  * as a result, the parent's upper bound is set to it's lower bound, and not below
7393  */
7394  if( parentnewbound < parentvar->glbdom.lb )
7395  {
7396  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7397  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7398  parentnewbound = parentvar->glbdom.lb;
7399  }
7400  }
7401  else
7402  parentnewbound = newbound;
7403  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7404  }
7405  else
7406  {
7407  SCIP_Real parentnewbound;
7408 
7409  /* a < 0 -> change lower bound of x */
7410  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7411  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, oldbound))
7412  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7413  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7414  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7415  {
7416  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7417  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7418  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7419  * as a result, the parent's lower bound is set to it's upper bound, and not above
7420  */
7421  if( parentnewbound > parentvar->glbdom.ub )
7422  {
7423  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7424  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7425  parentnewbound = parentvar->glbdom.ub;
7426  }
7427  }
7428  else
7429  parentnewbound = -newbound;
7430  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7431  }
7432  break;
7433 
7434  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7435  assert(parentvar->negatedvar != NULL);
7436  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7437  assert(parentvar->negatedvar->negatedvar == parentvar);
7438  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7439  parentvar->data.negate.constant - newbound) );
7440  break;
7441 
7442  default:
7443  SCIPerrorMessage("unknown variable status\n");
7444  return SCIP_INVALIDDATA;
7445  }
7446  }
7447 
7448  return SCIP_OKAY;
7449 }
7450 
7451 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7452  * information in variable
7453  */
7455  SCIP_VAR* var, /**< problem variable to change */
7456  BMS_BLKMEM* blkmem, /**< block memory */
7457  SCIP_SET* set, /**< global SCIP settings */
7458  SCIP_STAT* stat, /**< problem statistics */
7459  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7460  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7461  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7462  SCIP_Real newbound /**< new bound for variable */
7463  )
7464 {
7465  assert(var != NULL);
7466  assert(blkmem != NULL);
7467  assert(set != NULL);
7468  assert(var->scip == set->scip);
7469 
7470  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7471  * of the domain within feastol
7472  */
7473  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7474 
7475  /* adjust bound to integral value if variable is of integral type */
7476  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7477 
7478  /* check that the adjusted bound is feasible */
7479  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7480 
7481  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7482  {
7483  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7484  newbound = MIN(newbound, var->locdom.ub);
7485  }
7486  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7487 
7488  SCIPdebugMessage("changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7489 
7490  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) )
7491  return SCIP_OKAY;
7492 
7493  /* change bounds of attached variables */
7494  switch( SCIPvarGetStatus(var) )
7495  {
7497  if( var->data.original.transvar != NULL )
7498  {
7499  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7500  newbound) );
7501  }
7502  else
7503  {
7504  assert(set->stage == SCIP_STAGE_PROBLEM);
7505  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7506  }
7507  break;
7508 
7509  case SCIP_VARSTATUS_COLUMN:
7510  case SCIP_VARSTATUS_LOOSE:
7511  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7512  break;
7513 
7514  case SCIP_VARSTATUS_FIXED:
7515  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7516  return SCIP_INVALIDDATA;
7517 
7518  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7519  assert(var->data.aggregate.var != NULL);
7520  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7521  {
7522  SCIP_Real childnewbound;
7523 
7524  /* a > 0 -> change lower bound of y */
7525  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7526  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7528  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7529  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7530  else
7531  childnewbound = newbound;
7532  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7533  childnewbound) );
7534  }
7535  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7536  {
7537  SCIP_Real childnewbound;
7538 
7539  /* a < 0 -> change upper bound of y */
7540  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7541  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7543  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7544  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7545  else
7546  childnewbound = -newbound;
7547  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7548  childnewbound) );
7549  }
7550  else
7551  {
7552  SCIPerrorMessage("scalar is zero in aggregation\n");
7553  return SCIP_INVALIDDATA;
7554  }
7555  break;
7556 
7558  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7559  return SCIP_INVALIDDATA;
7560 
7561  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7562  assert(var->negatedvar != NULL);
7564  assert(var->negatedvar->negatedvar == var);
7565  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7566  var->data.negate.constant - newbound) );
7567  break;
7568 
7569  default:
7570  SCIPerrorMessage("unknown variable status\n");
7571  return SCIP_INVALIDDATA;
7572  }
7573 
7574  return SCIP_OKAY;
7575 }
7576 
7577 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7578  * information in variable
7579  */
7581  SCIP_VAR* var, /**< problem variable to change */
7582  BMS_BLKMEM* blkmem, /**< block memory */
7583  SCIP_SET* set, /**< global SCIP settings */
7584  SCIP_STAT* stat, /**< problem statistics */
7585  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7586  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7587  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7588  SCIP_Real newbound /**< new bound for variable */
7589  )
7590 {
7591  assert(var != NULL);
7592  assert(blkmem != NULL);
7593  assert(set != NULL);
7594  assert(var->scip == set->scip);
7595 
7596  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7597  * of the domain within feastol
7598  */
7599  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7600 
7601  /* adjust bound to integral value if variable is of integral type */
7602  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7603 
7604  /* check that the adjusted bound is feasible */
7605  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7606 
7607  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7608  {
7609  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7610  newbound = MAX(newbound, var->locdom.lb);
7611  }
7612  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7613 
7614  SCIPdebugMessage("changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7615 
7616  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) )
7617  return SCIP_OKAY;
7618 
7619  /* change bounds of attached variables */
7620  switch( SCIPvarGetStatus(var) )
7621  {
7623  if( var->data.original.transvar != NULL )
7624  {
7625  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7626  }
7627  else
7628  {
7629  assert(set->stage == SCIP_STAGE_PROBLEM);
7630  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7631  }
7632  break;
7633 
7634  case SCIP_VARSTATUS_COLUMN:
7635  case SCIP_VARSTATUS_LOOSE:
7636  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7637  break;
7638 
7639  case SCIP_VARSTATUS_FIXED:
7640  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7641  return SCIP_INVALIDDATA;
7642 
7643  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7644  assert(var->data.aggregate.var != NULL);
7645  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7646  {
7647  SCIP_Real childnewbound;
7648 
7649  /* a > 0 -> change upper bound of y */
7650  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7651  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7653  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7654  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7655  else
7656  childnewbound = newbound;
7657  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7658  childnewbound) );
7659  }
7660  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7661  {
7662  SCIP_Real childnewbound;
7663 
7664  /* a < 0 -> change lower bound of y */
7665  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7666  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7668  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7669  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7670  else
7671  childnewbound = -newbound;
7672  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7673  childnewbound) );
7674  }
7675  else
7676  {
7677  SCIPerrorMessage("scalar is zero in aggregation\n");
7678  return SCIP_INVALIDDATA;
7679  }
7680  break;
7681 
7683  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7684  return SCIP_INVALIDDATA;
7685 
7686  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7687  assert(var->negatedvar != NULL);
7689  assert(var->negatedvar->negatedvar == var);
7690  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7691  var->data.negate.constant - newbound) );
7692  break;
7693 
7694  default:
7695  SCIPerrorMessage("unknown variable status\n");
7696  return SCIP_INVALIDDATA;
7697  }
7698 
7699  return SCIP_OKAY;
7700 }
7701 
7702 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7703  * information in variable
7704  */
7706  SCIP_VAR* var, /**< problem variable to change */
7707  BMS_BLKMEM* blkmem, /**< block memory */
7708  SCIP_SET* set, /**< global SCIP settings */
7709  SCIP_STAT* stat, /**< problem statistics */
7710  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7711  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7712  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7713  SCIP_Real newbound, /**< new bound for variable */
7714  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7715  )
7716 {
7717  /* apply bound change to the LP data */
7718  switch( boundtype )
7719  {
7720  case SCIP_BOUNDTYPE_LOWER:
7721  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7722  case SCIP_BOUNDTYPE_UPPER:
7723  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7724  default:
7725  SCIPerrorMessage("unknown bound type\n");
7726  return SCIP_INVALIDDATA;
7727  }
7728 }
7729 
7730 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7732  SCIP_VAR* var, /**< problem variable to change */
7733  SCIP_SET* set, /**< global SCIP settings */
7734  SCIP_LP* lp, /**< current LP data */
7735  SCIP_Real newbound /**< new bound for variable */
7736  )
7737 {
7738  assert(var != NULL);
7739  assert(set != NULL);
7740  assert(var->scip == set->scip);
7741  assert(lp != NULL);
7742  assert(SCIPlpDiving(lp));
7743 
7744  /* adjust bound for integral variables */
7745  SCIPvarAdjustLb(var, set, &newbound);
7746 
7747  SCIPdebugMessage("changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7748 
7749  /* change bounds of attached variables */
7750  switch( SCIPvarGetStatus(var) )
7751  {
7753  assert(var->data.original.transvar != NULL);
7754  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7755  break;
7756 
7757  case SCIP_VARSTATUS_COLUMN:
7758  assert(var->data.col != NULL);
7759  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7760  break;
7761 
7762  case SCIP_VARSTATUS_LOOSE:
7763  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7764  return SCIP_INVALIDDATA;
7765 
7766  case SCIP_VARSTATUS_FIXED:
7767  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7768  return SCIP_INVALIDDATA;
7769 
7770  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7771  assert(var->data.aggregate.var != NULL);
7772  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7773  {
7774  SCIP_Real childnewbound;
7775 
7776  /* a > 0 -> change lower bound of y */
7777  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7778  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7779  else
7780  childnewbound = newbound;
7781  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7782  }
7783  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7784  {
7785  SCIP_Real childnewbound;
7786 
7787  /* a < 0 -> change upper bound of y */
7788  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7789  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7790  else
7791  childnewbound = -newbound;
7792  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7793  }
7794  else
7795  {
7796  SCIPerrorMessage("scalar is zero in aggregation\n");
7797  return SCIP_INVALIDDATA;
7798  }
7799  break;
7800 
7802  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7803  return SCIP_INVALIDDATA;
7804 
7805  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7806  assert(var->negatedvar != NULL);
7808  assert(var->negatedvar->negatedvar == var);
7809  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7810  break;
7811 
7812  default:
7813  SCIPerrorMessage("unknown variable status\n");
7814  return SCIP_INVALIDDATA;
7815  }
7816 
7817  return SCIP_OKAY;
7818 }
7819 
7820 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
7822  SCIP_VAR* var, /**< problem variable to change */
7823  SCIP_SET* set, /**< global SCIP settings */
7824  SCIP_LP* lp, /**< current LP data */
7825  SCIP_Real newbound /**< new bound for variable */
7826  )
7827 {
7828  assert(var != NULL);
7829  assert(set != NULL);
7830  assert(var->scip == set->scip);
7831  assert(lp != NULL);
7832  assert(SCIPlpDiving(lp));
7833 
7834  /* adjust bound for integral variables */
7835  SCIPvarAdjustUb(var, set, &newbound);
7836 
7837  SCIPdebugMessage("changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
7838 
7839  /* change bounds of attached variables */
7840  switch( SCIPvarGetStatus(var) )
7841  {
7843  assert(var->data.original.transvar != NULL);
7844  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
7845  break;
7846 
7847  case SCIP_VARSTATUS_COLUMN:
7848  assert(var->data.col != NULL);
7849  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
7850  break;
7851 
7852  case SCIP_VARSTATUS_LOOSE:
7853  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7854  return SCIP_INVALIDDATA;
7855 
7856  case SCIP_VARSTATUS_FIXED:
7857  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7858  return SCIP_INVALIDDATA;
7859 
7860  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7861  assert(var->data.aggregate.var != NULL);
7862  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7863  {
7864  SCIP_Real childnewbound;
7865 
7866  /* a > 0 -> change upper bound of y */
7867  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7868  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7869  else
7870  childnewbound = newbound;
7871  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7872  }
7873  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7874  {
7875  SCIP_Real childnewbound;
7876 
7877  /* a < 0 -> change lower bound of y */
7878  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7879  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7880  else
7881  childnewbound = -newbound;
7882  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7883  }
7884  else
7885  {
7886  SCIPerrorMessage("scalar is zero in aggregation\n");
7887  return SCIP_INVALIDDATA;
7888  }
7889  break;
7890 
7892  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7893  return SCIP_INVALIDDATA;
7894 
7895  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7896  assert(var->negatedvar != NULL);
7898  assert(var->negatedvar->negatedvar == var);
7899  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7900  break;
7901 
7902  default:
7903  SCIPerrorMessage("unknown variable status\n");
7904  return SCIP_INVALIDDATA;
7905  }
7906 
7907  return SCIP_OKAY;
7908 }
7909 
7910 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
7911  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
7912  * not updated if bounds of aggregation variables are changing
7913  *
7914  * calling this function for a non-multi-aggregated variable is not allowed
7915  */
7917  SCIP_VAR* var, /**< problem variable */
7918  SCIP_SET* set /**< global SCIP settings */
7919  )
7920 {
7921  int i;
7922  SCIP_Real lb;
7923  SCIP_Real bnd;
7924  SCIP_VAR* aggrvar;
7925  SCIP_Bool posinf;
7926  SCIP_Bool neginf;
7927 
7928  assert(var != NULL);
7929  assert(set != NULL);
7930  assert(var->scip == set->scip);
7932 
7933  posinf = FALSE;
7934  neginf = FALSE;
7935  lb = var->data.multaggr.constant;
7936  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
7937  {
7938  aggrvar = var->data.multaggr.vars[i];
7939  if( var->data.multaggr.scalars[i] > 0.0 )
7940  {
7941  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
7942 
7943  if( SCIPsetIsInfinity(set, bnd) )
7944  posinf = TRUE;
7945  else if( SCIPsetIsInfinity(set, -bnd) )
7946  neginf = TRUE;
7947  else
7948  lb += var->data.multaggr.scalars[i] * bnd;
7949  }
7950  else
7951  {
7952  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
7953 
7954  if( SCIPsetIsInfinity(set, -bnd) )
7955  posinf = TRUE;
7956  else if( SCIPsetIsInfinity(set, bnd) )
7957  neginf = TRUE;
7958  else
7959  lb += var->data.multaggr.scalars[i] * bnd;
7960  }
7961 
7962  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
7963  * variable
7964  */
7965  if( neginf )
7966  return SCIPvarGetLbLocal(var);
7967  }
7968 
7969  /* if positive infinity flag was set to true return infinity */
7970  if( posinf )
7971  return SCIPsetInfinity(set);
7972 
7973  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
7974 }
7975 
7976 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
7977  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
7978  * not updated if bounds of aggregation variables are changing
7979  *
7980  * calling this function for a non-multi-aggregated variable is not allowed
7981  */
7983  SCIP_VAR* var, /**< problem variable */
7984  SCIP_SET* set /**< global SCIP settings */
7985  )
7986 {
7987  int i;
7988  SCIP_Real ub;
7989  SCIP_Real bnd;
7990  SCIP_VAR* aggrvar;
7991  SCIP_Bool posinf;
7992  SCIP_Bool neginf;
7993 
7994  assert(var != NULL);
7995  assert(set != NULL);
7996  assert(var->scip == set->scip);
7998 
7999  posinf = FALSE;
8000  neginf = FALSE;
8001  ub = var->data.multaggr.constant;
8002  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8003  {
8004  aggrvar = var->data.multaggr.vars[i];
8005  if( var->data.multaggr.scalars[i] > 0.0 )
8006  {
8007  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8008 
8009  if( SCIPsetIsInfinity(set, bnd) )
8010  posinf = TRUE;
8011  else if( SCIPsetIsInfinity(set, -bnd) )
8012  neginf = TRUE;
8013  else
8014  ub += var->data.multaggr.scalars[i] * bnd;
8015  }
8016  else
8017  {
8018  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8019 
8020  if( SCIPsetIsInfinity(set, -bnd) )
8021  posinf = TRUE;
8022  else if( SCIPsetIsInfinity(set, bnd) )
8023  neginf = TRUE;
8024  else
8025  ub += var->data.multaggr.scalars[i] * bnd;
8026  }
8027 
8028  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8029  * variable
8030  */
8031  if( posinf )
8032  return SCIPvarGetUbLocal(var);
8033  }
8034 
8035  /* if negative infinity flag was set to true return -infinity */
8036  if( neginf )
8037  return -SCIPsetInfinity(set);
8038 
8039  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8040 }
8041 
8042 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8043  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8044  * not updated if bounds of aggregation variables are changing
8045  *
8046  * calling this function for a non-multi-aggregated variable is not allowed
8047  */
8049  SCIP_VAR* var, /**< problem variable */
8050  SCIP_SET* set /**< global SCIP settings */
8051  )
8052 {
8053  int i;
8054  SCIP_Real lb;
8055  SCIP_Real bnd;
8056  SCIP_VAR* aggrvar;
8057  SCIP_Bool posinf;
8058  SCIP_Bool neginf;
8059 
8060  assert(var != NULL);
8061  assert(set != NULL);
8062  assert(var->scip == set->scip);
8064 
8065  posinf = FALSE;
8066  neginf = FALSE;
8067  lb = var->data.multaggr.constant;
8068  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8069  {
8070  aggrvar = var->data.multaggr.vars[i];
8071  if( var->data.multaggr.scalars[i] > 0.0 )
8072  {
8073  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8074 
8075  if( SCIPsetIsInfinity(set, bnd) )
8076  posinf = TRUE;
8077  else if( SCIPsetIsInfinity(set, -bnd) )
8078  neginf = TRUE;
8079  else
8080  lb += var->data.multaggr.scalars[i] * bnd;
8081  }
8082  else
8083  {
8084  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8085 
8086  if( SCIPsetIsInfinity(set, -bnd) )
8087  posinf = TRUE;
8088  else if( SCIPsetIsInfinity(set, bnd) )
8089  neginf = TRUE;
8090  else
8091  lb += var->data.multaggr.scalars[i] * bnd;
8092  }
8093 
8094  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8095  * variable
8096  */
8097  if( neginf )
8098  return SCIPvarGetLbGlobal(var);
8099  }
8100 
8101  /* if positive infinity flag was set to true return infinity */
8102  if( posinf )
8103  return SCIPsetInfinity(set);
8104 
8105  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8106 }
8107 
8108 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8109  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8110  * not updated if bounds of aggregation variables are changing
8111  *
8112  * calling this function for a non-multi-aggregated variable is not allowed
8113  */
8115  SCIP_VAR* var, /**< problem variable */
8116  SCIP_SET* set /**< global SCIP settings */
8117  )
8118 {
8119  int i;
8120  SCIP_Real ub;
8121  SCIP_Real bnd;
8122  SCIP_VAR* aggrvar;
8123  SCIP_Bool posinf;
8124  SCIP_Bool neginf;
8125 
8126  assert(var != NULL);
8127  assert(set != NULL);
8128  assert(var->scip == set->scip);
8130 
8131  posinf = FALSE;
8132  neginf = FALSE;
8133  ub = var->data.multaggr.constant;
8134  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8135  {
8136  aggrvar = var->data.multaggr.vars[i];
8137  if( var->data.multaggr.scalars[i] > 0.0 )
8138  {
8139  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8140 
8141  if( SCIPsetIsInfinity(set, bnd) )
8142  posinf = TRUE;
8143  else if( SCIPsetIsInfinity(set, -bnd) )
8144  neginf = TRUE;
8145  else
8146  ub += var->data.multaggr.scalars[i] * bnd;
8147  }
8148  else
8149  {
8150  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8151 
8152  if( SCIPsetIsInfinity(set, -bnd) )
8153  posinf = TRUE;
8154  else if( SCIPsetIsInfinity(set, bnd) )
8155  neginf = TRUE;
8156  else
8157  ub += var->data.multaggr.scalars[i] * bnd;
8158  }
8159 
8160  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8161  * variable
8162  */
8163  if( posinf )
8164  return SCIPvarGetUbGlobal(var);
8165  }
8166 
8167  /* if negative infinity flag was set to true return -infinity */
8168  if( neginf )
8169  return -SCIPsetInfinity(set);
8170 
8171  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8172 }
8173 
8174 /** adds a hole to the original domain of the variable */
8176  SCIP_VAR* var, /**< problem variable */
8177  BMS_BLKMEM* blkmem, /**< block memory */
8178  SCIP_SET* set, /**< global SCIP settings */
8179  SCIP_Real left, /**< left bound of open interval in new hole */
8180  SCIP_Real right /**< right bound of open interval in new hole */
8181  )
8182 {
8183  SCIP_Bool added;
8184 
8185  assert(var != NULL);
8186  assert(!SCIPvarIsTransformed(var));
8188  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8189  assert(set != NULL);
8190  assert(var->scip == set->scip);
8191  assert(set->stage == SCIP_STAGE_PROBLEM);
8192 
8193  SCIPdebugMessage("adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8194 
8195  if( SCIPsetIsEQ(set, left, right) )
8196  return SCIP_OKAY;
8197 
8198  /* the interval should not be empty */
8199  assert(SCIPsetIsLT(set, left, right));
8200 
8201  /* the the interval bound should already be adjusted */
8202  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8203  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8204 
8205  /* the the interval should lay between the lower and upper bound */
8206  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8207  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8208 
8209  /* add domain hole */
8210  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8211 
8212  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8213  if( added )
8214  {
8215  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8216  }
8217 
8218  /**@todo add hole in parent and child variables (just like with bound changes);
8219  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8220  */
8221 
8222  return SCIP_OKAY;
8223 }
8224 
8225 /** performs the current add of domain, changes all parents accordingly */
8226 static
8228  SCIP_VAR* var, /**< problem variable */
8229  BMS_BLKMEM* blkmem, /**< block memory */
8230  SCIP_SET* set, /**< global SCIP settings */
8231  SCIP_STAT* stat, /**< problem statistics */
8232  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8233  SCIP_Real left, /**< left bound of open interval in new hole */
8234  SCIP_Real right, /**< right bound of open interval in new hole */
8235  SCIP_Bool* added /**< pointer to store whether the hole was added */
8236  )
8237 {
8238  SCIP_VAR* parentvar;
8239  SCIP_Real newlb;
8240  SCIP_Real newub;
8241  int i;
8242 
8243  assert(var != NULL);
8244  assert(added != NULL);
8245  assert(blkmem != NULL);
8246 
8247  /* the interval should not be empty */
8248  assert(SCIPsetIsLT(set, left, right));
8249 
8250  /* the interval bound should already be adjusted */
8251  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8252  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8253 
8254  /* the interval should lay between the lower and upper bound */
8255  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8256  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8257 
8258  /* @todo add debugging mechanism for holes when using a debugging solution */
8259 
8260  /* add hole to hole list */
8261  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8262 
8263  /* check if the hole is redundant */
8264  if( !(*added) )
8265  return SCIP_OKAY;
8266 
8267  /* current bounds */
8268  newlb = var->glbdom.lb;
8269  newub = var->glbdom.ub;
8270 
8271  /* merge domain holes */
8272  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8273 
8274  /* the bound should not be changed */
8275  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8276  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8277 
8278  /* issue bound change event */
8279  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8280  if( var->eventfilter != NULL )
8281  {
8282  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8283  }
8284 
8285  /* process parent variables */
8286  for( i = 0; i < var->nparentvars; ++i )
8287  {
8288  SCIP_Real parentnewleft;
8289  SCIP_Real parentnewright;
8290  SCIP_Bool localadded;
8291 
8292  parentvar = var->parentvars[i];
8293  assert(parentvar != NULL);
8294 
8295  switch( SCIPvarGetStatus(parentvar) )
8296  {
8298  parentnewleft = left;
8299  parentnewright = right;
8300  break;
8301 
8302  case SCIP_VARSTATUS_COLUMN:
8303  case SCIP_VARSTATUS_LOOSE:
8304  case SCIP_VARSTATUS_FIXED:
8306  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8307  return SCIP_INVALIDDATA;
8308 
8309  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8310  assert(parentvar->data.aggregate.var == var);
8311 
8312  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8313  {
8314  /* a > 0 -> change upper bound of x */
8315  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8316  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8317  }
8318  else
8319  {
8320  /* a < 0 -> change lower bound of x */
8321  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8322 
8323  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8324  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8325  }
8326  break;
8327 
8328  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8329  assert(parentvar->negatedvar != NULL);
8330  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8331  assert(parentvar->negatedvar->negatedvar == parentvar);
8332 
8333  parentnewright = -left + parentvar->data.negate.constant;
8334  parentnewleft = -right + parentvar->data.negate.constant;
8335  break;
8336 
8337  default:
8338  SCIPerrorMessage("unknown variable status\n");
8339  return SCIP_INVALIDDATA;
8340  }
8341 
8342  SCIPdebugMessage("add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8343 
8344  /* perform hole added for parent variable */
8345  assert(blkmem != NULL);
8346  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8347  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8348  parentnewleft, parentnewright, &localadded) );
8349  assert(localadded);
8350  }
8351 
8352  return SCIP_OKAY;
8353 }
8354 
8355 /** adds a hole to the variable's global and local domain */
8357  SCIP_VAR* var, /**< problem variable */
8358  BMS_BLKMEM* blkmem, /**< block memory */
8359  SCIP_SET* set, /**< global SCIP settings */
8360  SCIP_STAT* stat, /**< problem statistics */
8361  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8362  SCIP_Real left, /**< left bound of open interval in new hole */
8363  SCIP_Real right, /**< right bound of open interval in new hole */
8364  SCIP_Bool* added /**< pointer to store whether the hole was added */
8365  )
8366 {
8367  SCIP_Real childnewleft;
8368  SCIP_Real childnewright;
8369 
8370  assert(var != NULL);
8371  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8372  assert(blkmem != NULL);
8373  assert(added != NULL);
8374 
8375  SCIPdebugMessage("adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8376 
8377  /* the interval should not be empty */
8378  assert(SCIPsetIsLT(set, left, right));
8379 
8380  /* the the interval bound should already be adjusted */
8381  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8382  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8383 
8384  /* the the interval should lay between the lower and upper bound */
8385  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8386  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8387 
8388  /* change bounds of attached variables */
8389  switch( SCIPvarGetStatus(var) )
8390  {
8392  if( var->data.original.transvar != NULL )
8393  {
8394  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8395  left, right, added) );
8396  }
8397  else
8398  {
8399  assert(set->stage == SCIP_STAGE_PROBLEM);
8400 
8401  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8402  if( *added )
8403  {
8404  SCIP_Bool localadded;
8405 
8406  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8407  }
8408  }
8409  break;
8410 
8411  case SCIP_VARSTATUS_COLUMN:
8412  case SCIP_VARSTATUS_LOOSE:
8413  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8414  if( *added )
8415  {
8416  SCIP_Bool localadded;
8417 
8418  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8419  }
8420  break;
8421 
8422  case SCIP_VARSTATUS_FIXED:
8423  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8424  return SCIP_INVALIDDATA;
8425 
8426  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8427  assert(var->data.aggregate.var != NULL);
8428 
8429  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8430  {
8431  /* a > 0 -> change lower bound of y */
8432  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8433  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8434  }
8435  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8436  {
8437  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8438  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8439  }
8440  else
8441  {
8442  SCIPerrorMessage("scalar is zero in aggregation\n");
8443  return SCIP_INVALIDDATA;
8444  }
8445  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8446  childnewleft, childnewright, added) );
8447  break;
8448 
8450  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8451  return SCIP_INVALIDDATA;
8452 
8453  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8454  assert(var->negatedvar != NULL);
8456  assert(var->negatedvar->negatedvar == var);
8457 
8458  childnewright = -left + var->data.negate.constant;
8459  childnewleft = -right + var->data.negate.constant;
8460 
8461  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8462  childnewleft, childnewright, added) );
8463  break;
8464 
8465  default:
8466  SCIPerrorMessage("unknown variable status\n");
8467  return SCIP_INVALIDDATA;
8468  }
8469 
8470  return SCIP_OKAY;
8471 }
8472 
8473 /** performs the current add of domain, changes all parents accordingly */
8474 static
8476  SCIP_VAR* var, /**< problem variable */
8477  BMS_BLKMEM* blkmem, /**< block memory */
8478  SCIP_SET* set, /**< global SCIP settings */
8479  SCIP_STAT* stat, /**< problem statistics */
8480  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8481  SCIP_Real left, /**< left bound of open interval in new hole */
8482  SCIP_Real right, /**< right bound of open interval in new hole */
8483  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8484  )
8485 {
8486  SCIP_VAR* parentvar;
8487  SCIP_Real newlb;
8488  SCIP_Real newub;
8489  int i;
8490 
8491  assert(var != NULL);
8492  assert(added != NULL);
8493  assert(blkmem != NULL);
8494 
8495  /* the interval should not be empty */
8496  assert(SCIPsetIsLT(set, left, right));
8497 
8498  /* the the interval bound should already be adjusted */
8499  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8500  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8501 
8502  /* the the interval should lay between the lower and upper bound */
8503  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8504  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8505 
8506  /* add hole to hole list */
8507  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8508 
8509  /* check if the hole is redundant */
8510  if( !(*added) )
8511  return SCIP_OKAY;
8512 
8513  /* current bounds */
8514  newlb = var->locdom.lb;
8515  newub = var->locdom.ub;
8516 
8517  /* merge domain holes */
8518  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8519 
8520  /* the bound should not be changed */
8521  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8522  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8523 
8524 #if 0
8525  /* issue bound change event */
8526  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8527  if( var->eventfilter != NULL )
8528  {
8529  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8530  }
8531 #endif
8532 
8533  /* process parent variables */
8534  for( i = 0; i < var->nparentvars; ++i )
8535  {
8536  SCIP_Real parentnewleft;
8537  SCIP_Real parentnewright;
8538  SCIP_Bool localadded;
8539 
8540  parentvar = var->parentvars[i];
8541  assert(parentvar != NULL);
8542 
8543  switch( SCIPvarGetStatus(parentvar) )
8544  {
8546  parentnewleft = left;
8547  parentnewright = right;
8548  break;
8549 
8550  case SCIP_VARSTATUS_COLUMN:
8551  case SCIP_VARSTATUS_LOOSE:
8552  case SCIP_VARSTATUS_FIXED:
8554  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8555  return SCIP_INVALIDDATA;
8556 
8557  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8558  assert(parentvar->data.aggregate.var == var);
8559 
8560  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8561  {
8562  /* a > 0 -> change upper bound of x */
8563  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8564  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8565  }
8566  else
8567  {
8568  /* a < 0 -> change lower bound of x */
8569  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8570 
8571  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8572  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8573  }
8574  break;
8575 
8576  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8577  assert(parentvar->negatedvar != NULL);
8578  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8579  assert(parentvar->negatedvar->negatedvar == parentvar);
8580 
8581  parentnewright = -left + parentvar->data.negate.constant;
8582  parentnewleft = -right + parentvar->data.negate.constant;
8583  break;
8584 
8585  default:
8586  SCIPerrorMessage("unknown variable status\n");
8587  return SCIP_INVALIDDATA;
8588  }
8589 
8590  SCIPdebugMessage("add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8591 
8592  /* perform hole added for parent variable */
8593  assert(blkmem != NULL);
8594  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8595  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8596  parentnewleft, parentnewright, &localadded) );
8597  assert(localadded);
8598  }
8599 
8600  return SCIP_OKAY;
8601 }
8602 
8603 /** adds a hole to the variable's current local domain */
8605  SCIP_VAR* var, /**< problem variable */
8606  BMS_BLKMEM* blkmem, /**< block memory */
8607  SCIP_SET* set, /**< global SCIP settings */
8608  SCIP_STAT* stat, /**< problem statistics */
8609  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8610  SCIP_Real left, /**< left bound of open interval in new hole */
8611  SCIP_Real right, /**< right bound of open interval in new hole */
8612  SCIP_Bool* added /**< pointer to store whether the hole was added */
8613  )
8614 {
8615  SCIP_Real childnewleft;
8616  SCIP_Real childnewright;
8617 
8618  SCIPdebugMessage("adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8619 
8620  assert(var != NULL);
8621  assert(set != NULL);
8622  assert(var->scip == set->scip);
8623  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8624  assert(blkmem != NULL);
8625  assert(added != NULL);
8626 
8627  /* the interval should not be empty */
8628  assert(SCIPsetIsLT(set, left, right));
8629 
8630  /* the the interval bound should already be adjusted */
8631  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8632  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8633 
8634  /* the the interval should lay between the lower and upper bound */
8635  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8636  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8637 
8638  /* change bounds of attached variables */
8639  switch( SCIPvarGetStatus(var) )
8640  {
8642  if( var->data.original.transvar != NULL )
8643  {
8644  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8645  left, right, added) );
8646  }
8647  else
8648  {
8649  assert(set->stage == SCIP_STAGE_PROBLEM);
8650 
8651  stat->domchgcount++;
8652  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8653  }
8654  break;
8655 
8656  case SCIP_VARSTATUS_COLUMN:
8657  case SCIP_VARSTATUS_LOOSE:
8658  stat->domchgcount++;
8659  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8660  break;
8661 
8662  case SCIP_VARSTATUS_FIXED:
8663  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8664  return SCIP_INVALIDDATA;
8665 
8666  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8667  assert(var->data.aggregate.var != NULL);
8668 
8669  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8670  {
8671  /* a > 0 -> change lower bound of y */
8672  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8673  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8674  }
8675  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8676  {
8677  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8678  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8679  }
8680  else
8681  {
8682  SCIPerrorMessage("scalar is zero in aggregation\n");
8683  return SCIP_INVALIDDATA;
8684  }
8685  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8686  childnewleft, childnewright, added) );
8687  break;
8688 
8690  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8691  return SCIP_INVALIDDATA;
8692 
8693  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8694  assert(var->negatedvar != NULL);
8696  assert(var->negatedvar->negatedvar == var);
8697 
8698  childnewright = -left + var->data.negate.constant;
8699  childnewleft = -right + var->data.negate.constant;
8700 
8701  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8702  break;
8703 
8704  default:
8705  SCIPerrorMessage("unknown variable status\n");
8706  return SCIP_INVALIDDATA;
8707  }
8708 
8709  return SCIP_OKAY;
8710 }
8711 
8712 /** resets the global and local bounds of original variable to their original values */
8714  SCIP_VAR* var, /**< problem variable */
8715  BMS_BLKMEM* blkmem, /**< block memory */
8716  SCIP_SET* set, /**< global SCIP settings */
8717  SCIP_STAT* stat /**< problem statistics */
8718  )
8719 {
8720  assert(var != NULL);
8721  assert(set != NULL);
8722  assert(var->scip == set->scip);
8723  assert(SCIPvarIsOriginal(var));
8724  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8725  * the transformed variable has been fixed */
8726  assert(SCIPvarGetTransVar(var) == NULL);
8727 
8728  /* copy the original bounds back to the global and local bounds */
8729  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8730  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8731  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8732  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8733 
8734  /* free the global and local holelists and duplicate the original ones */
8735  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8736  holelistFree(&var->glbdom.holelist, blkmem);
8737  holelistFree(&var->locdom.holelist, blkmem);
8738  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8739  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8740 
8741  return SCIP_OKAY;
8742 }
8743 
8744 /** issues a IMPLADDED event on the given variable */
8745 static
8747  SCIP_VAR* var, /**< problem variable to change */
8748  BMS_BLKMEM* blkmem, /**< block memory */
8749  SCIP_SET* set, /**< global SCIP settings */
8750  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8751  )
8752 {
8753  SCIP_EVENT* event;
8754 
8755  assert(var != NULL);
8756 
8757  /* issue IMPLADDED event on variable */
8758  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8759  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8760 
8761  return SCIP_OKAY;
8762 }
8763 
8764 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8765 static
8767  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8768  BMS_BLKMEM* blkmem, /**< block memory */
8769  SCIP_SET* set, /**< global SCIP settings */
8770  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8771  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8772  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8773  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8774  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8775  )
8776 {
8777  SCIP_Bool added;
8778 
8779  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8780  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
8781  * variable of the aggregated variable might be the same as the one its gets aggregated too.
8782  *
8783  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
8784  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
8785  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
8786  * variable bound can be ignored.
8787  *
8788  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
8789  * equivalence of the variables should be checked here.
8790  */
8791  if( var == vbvar )
8792  {
8793  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
8794  * can be checked via the global bounds of the variable */
8795 #ifndef NDEBUG
8796  SCIP_Real lb;
8797  SCIP_Real ub;
8798 
8799  lb = SCIPvarGetLbGlobal(var);
8800  ub = SCIPvarGetUbGlobal(var);
8801 
8802  if(vbtype == SCIP_BOUNDTYPE_LOWER)
8803  {
8804  if( vbcoef > 0.0 )
8805  {
8806  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
8807  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
8808  }
8809  else
8810  {
8811  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
8812  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
8813  }
8814  }
8815  else
8816  {
8817  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
8818  if( vbcoef > 0.0 )
8819  {
8820  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
8821  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
8822  }
8823  else
8824  {
8825  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
8826  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
8827  }
8828  }
8829 #endif
8830  SCIPdebugMessage("redundant variable bound: <%s> %s %g<%s> %+g\n",
8831  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8832 
8833  return SCIP_OKAY;
8834  }
8835 
8836  SCIPdebugMessage("adding variable bound: <%s> %s %g<%s> %+g\n",
8837  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8838 
8839  /* check variable bound on debugging solution */
8840  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
8841 
8842  /* perform the addition */
8843  if( vbtype == SCIP_BOUNDTYPE_LOWER )
8844  {
8845  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8846  }
8847  else
8848  {
8849  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8850  }
8851  var->closestvblpcount = -1;
8852 
8853  if( added )
8854  {
8855  /* issue IMPLADDED event */
8856  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
8857  }
8858 
8859  return SCIP_OKAY;
8860 }
8861 
8862 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
8863 static
8864 void checkImplic(
8865  SCIP_SET* set, /**< global SCIP settings */
8866  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8867  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8868  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8869  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
8870  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
8871  )
8872 {
8873  SCIP_Real impllb;
8874  SCIP_Real implub;
8875 
8876  assert(redundant != NULL);
8877  assert(infeasible != NULL);
8878 
8879  impllb = SCIPvarGetLbGlobal(implvar);
8880  implub = SCIPvarGetUbGlobal(implvar);
8881  if( impltype == SCIP_BOUNDTYPE_LOWER )
8882  {
8883  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
8884  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
8885  }
8886  else
8887  {
8888  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
8889  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
8890  }
8891 }
8892 
8893 /** applies the given implication, if it is not redundant */
8894 static
8896  BMS_BLKMEM* blkmem, /**< block memory */
8897  SCIP_SET* set, /**< global SCIP settings */
8898  SCIP_STAT* stat, /**< problem statistics */
8899  SCIP_PROB* transprob, /**< transformed problem */
8900  SCIP_PROB* origprob, /**< original problem */
8901  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
8902  SCIP_REOPT* reopt, /**< reoptimization data structure */
8903  SCIP_LP* lp, /**< current LP data */
8904  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8905  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8906  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8907  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8908  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8909  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8910  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
8911  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
8912  )
8913 {
8914  SCIP_Real implub;
8915  SCIP_Real impllb;
8916 
8917  assert(infeasible != NULL);
8918 
8919  *infeasible = FALSE;
8920 
8921  implub = SCIPvarGetUbGlobal(implvar);
8922  impllb = SCIPvarGetLbGlobal(implvar);
8923  if( impltype == SCIP_BOUNDTYPE_LOWER )
8924  {
8925  if( SCIPsetIsFeasGT(set, implbound, implub) )
8926  {
8927  /* the implication produces a conflict: the problem is infeasible */
8928  *infeasible = TRUE;
8929  }
8930  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
8931  {
8932  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8933  * with the local bound, in this case we need to store the bound change as pending bound change
8934  */
8935  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8936  {
8937  assert(tree != NULL);
8938  assert(transprob != NULL);
8939  assert(SCIPprobIsTransformed(transprob));
8940 
8941  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8942  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
8943  }
8944  else
8945  {
8946  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
8947  }
8948 
8949  if( nbdchgs != NULL )
8950  (*nbdchgs)++;
8951  }
8952  }
8953  else
8954  {
8955  if( SCIPsetIsFeasLT(set, implbound, impllb) )
8956  {
8957  /* the implication produces a conflict: the problem is infeasible */
8958  *infeasible = TRUE;
8959  }
8960  else if( SCIPsetIsFeasLT(set, implbound, implub) )
8961  {
8962  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8963  * with the local bound, in this case we need to store the bound change as pending bound change
8964  */
8965  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8966  {
8967  assert(tree != NULL);
8968  assert(transprob != NULL);
8969  assert(SCIPprobIsTransformed(transprob));
8970 
8971  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8972  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
8973  }
8974  else
8975  {
8976  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
8977  }
8978 
8979  if( nbdchgs != NULL )
8980  (*nbdchgs)++;
8981  }
8982  }
8983 
8984  return SCIP_OKAY;
8985 }
8986 
8987 /** actually performs the addition of an implication to the variable's implication arrays,
8988  * and adds the corresponding implication or variable bound to the implied variable;
8989  * if the implication is conflicting, the variable is fixed to the opposite value;
8990  * if the variable is already fixed to the given value, the implication is performed immediately;
8991  * if the implication is redundant with respect to the variables' global bounds, it is ignored
8992  */
8993 static
8995  SCIP_VAR* var, /**< problem variable */
8996  BMS_BLKMEM* blkmem, /**< block memory */
8997  SCIP_SET* set, /**< global SCIP settings */
8998  SCIP_STAT* stat, /**< problem statistics */
8999  SCIP_PROB* transprob, /**< transformed problem */
9000  SCIP_PROB* origprob, /**< original problem */
9001  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9002  SCIP_REOPT* reopt, /**< reoptimization data structure */
9003  SCIP_LP* lp, /**< current LP data */
9004  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9005  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9006  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9007  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9008  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9009  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9010  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9011  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9012  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9013  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9014  SCIP_Bool* added /**< pointer to store whether an implication was added */
9015  )
9016 {
9017  SCIP_Bool redundant;
9018  SCIP_Bool conflict;
9019 
9020  assert(var != NULL);
9021  assert(SCIPvarIsActive(var));
9023  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9024  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9025  assert(infeasible != NULL);
9026  assert(added != NULL);
9027 
9028  /* check implication on debugging solution */
9029  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9030 
9031  *infeasible = FALSE;
9032  *added = FALSE;
9033 
9034  /* check, if the implication is redundant or infeasible */
9035  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9036  assert(!redundant || !conflict);
9037  if( redundant )
9038  return SCIP_OKAY;
9039 
9040  if( var == implvar )
9041  {
9042  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9043  * x == varfixing => x < 0 or x > 1
9044  */
9045  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9046  conflict = TRUE;
9047  else
9048  {
9049  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9050  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9051  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9052  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9053  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9054  if( !conflict )
9055  return SCIP_OKAY;
9056  }
9057  }
9058 
9059  /* check, if the variable is already fixed */
9060  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9061  {
9062  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9063  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9064  {
9065  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9066  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9067  }
9068  return SCIP_OKAY;
9069  }
9070 
9071  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9072  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9073 
9074  if( !conflict )
9075  {
9076  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9077 
9078  if( SCIPvarIsBinary(implvar) )
9079  {
9080  SCIP_VAR* vars[2];
9081  SCIP_Bool vals[2];
9082 
9083  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9084  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9085 
9086  vars[0] = var;
9087  vars[1] = implvar;
9088  vals[0] = varfixing;
9089  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9090 
9091  /* add the clique to the clique table */
9092  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9093  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9094 
9095  if( !conflict )
9096  return SCIP_OKAY;
9097  }
9098  else
9099  {
9100  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9101  SCIPdebugMessage("adding implication: <%s> == %u ==> <%s> %s %g\n",
9102  SCIPvarGetName(var), varfixing,
9103  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9104  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9105  isshortcut, &conflict, added) );
9106  }
9107  }
9108  assert(!conflict || !(*added));
9109 
9110  /* on conflict, fix the variable to the opposite value */
9111  if( conflict )
9112  {
9113  SCIPdebugMessage(" -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9114 
9115  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9116  * with the local bound, in this case we need to store the bound change as pending bound change
9117  */
9118  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9119  {
9120  assert(tree != NULL);
9121  assert(transprob != NULL);
9122  assert(SCIPprobIsTransformed(transprob));
9123 
9124  if( varfixing )
9125  {
9126  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9127  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9128  }
9129  else
9130  {
9131  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9132  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9133  }
9134  }
9135  else
9136  {
9137  if( varfixing )
9138  {
9139  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9140  }
9141  else
9142  {
9143  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9144  }
9145  }
9146  if( nbdchgs != NULL )
9147  (*nbdchgs)++;
9148 
9149  return SCIP_OKAY;
9150  }
9151  else if( *added )
9152  {
9153  /* issue IMPLADDED event */
9154  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9155  }
9156  else
9157  {
9158  /* the implication was redundant: the inverse is also redundant */
9159  return SCIP_OKAY;
9160  }
9161 
9162  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9163 
9164  /* check, whether implied variable is binary */
9165  if( !SCIPvarIsBinary(implvar) )
9166  {
9167  SCIP_Real lb;
9168  SCIP_Real ub;
9169 
9170  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9171  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9172  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9173  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9174  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9175  * for numerical reasons, ignore variable bounds with large absolute coefficient
9176  */
9177  lb = SCIPvarGetLbGlobal(implvar);
9178  ub = SCIPvarGetUbGlobal(implvar);
9179  if( impltype == SCIP_BOUNDTYPE_UPPER )
9180  {
9181  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9182  {
9183  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9184  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9185  }
9186  }
9187  else
9188  {
9189  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9190  {
9191  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9192  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9193  }
9194  }
9195  }
9196 
9197  return SCIP_OKAY;
9198 }
9199 
9200 /** adds transitive closure for binary implication x = a -> y = b */
9201 static
9203  SCIP_VAR* var, /**< problem variable */
9204  BMS_BLKMEM* blkmem, /**< block memory */
9205  SCIP_SET* set, /**< global SCIP settings */
9206  SCIP_STAT* stat, /**< problem statistics */
9207  SCIP_PROB* transprob, /**< transformed problem */
9208  SCIP_PROB* origprob, /**< original problem */
9209  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9210  SCIP_REOPT* reopt, /**< reoptimization data structure */
9211  SCIP_LP* lp, /**< current LP data */
9212  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9213  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9214  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9215  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9216  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9217  SCIP_Bool implvarfixing, /**< fixing b in implication */
9218  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9219  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9220  )
9221 {
9222  SCIP_VAR** implvars;
9223  SCIP_BOUNDTYPE* impltypes;
9224  SCIP_Real* implbounds;
9225  int nimpls;
9226  int i;
9227 
9228  *infeasible = FALSE;
9229 
9230  /* binary variable: implications of implvar */
9231  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9232  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9233  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9234  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9235 
9236  /* if variable has too many implications, the implication graph may become too dense */
9237  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9238 
9239  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9240  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9241  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9242  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9243  * only thing that can happen is that we add the same implication twice - this does no harm
9244  */
9245  while ( i >= 0 && !(*infeasible) )
9246  {
9247  SCIP_Bool added;
9248 
9249  assert(implvars[i] != implvar);
9250 
9251  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9252  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9253  */
9254  if( SCIPvarIsActive(implvars[i]) )
9255  {
9256  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9257  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9258  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9259  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9260  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9261  }
9262  --i;
9263  }
9264 
9265  return SCIP_OKAY;
9266 }
9267 
9268 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9269  * implication to the variable's implication list;
9270  * if the implication is conflicting, the variable is fixed to the opposite value;
9271  * if the variable is already fixed to the given value, the implication is performed immediately;
9272  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9273  */
9274 static
9276  SCIP_VAR* var, /**< problem variable */
9277  BMS_BLKMEM* blkmem, /**< block memory */
9278  SCIP_SET* set, /**< global SCIP settings */
9279  SCIP_STAT* stat, /**< problem statistics */
9280  SCIP_PROB* transprob, /**< transformed problem */
9281  SCIP_PROB* origprob, /**< original problem */
9282  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9283  SCIP_REOPT* reopt, /**< reoptimization data structure */
9284  SCIP_LP* lp, /**< current LP data */
9285  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9286  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9287  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9288  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9289  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9290  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9291  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9292  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9293  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9294  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9295  )
9296 {
9297  SCIP_Bool added;
9298 
9299  assert(var != NULL);
9300  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9301  assert(SCIPvarIsActive(var));
9302  assert(implvar != NULL);
9303  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9304  assert(infeasible != NULL);
9305 
9306  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9307  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9308  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9309 
9310  if( *infeasible || var == implvar || !transitive || !added )
9311  return SCIP_OKAY;
9312 
9313  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9314 
9315  /* add transitive closure */
9316  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9317  {
9318  SCIP_Bool implvarfixing;
9319 
9320  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9321 
9322  /* binary variable: implications of implvar */
9323  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9324  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9325 
9326  /* inverse implication */
9327  if( !(*infeasible) )
9328  {
9329  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9330  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9331  }
9332  }
9333  else
9334  {
9335  /* non-binary variable: variable lower bounds of implvar */
9336  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9337  {
9338  SCIP_VAR** vlbvars;
9339  SCIP_Real* vlbcoefs;
9340  SCIP_Real* vlbconstants;
9341  int nvlbvars;
9342  int i;
9343 
9344  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9345  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9346  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9347  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9348 
9349  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9350  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9351  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9352  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9353  * is that we add the same implication twice - this does no harm
9354  */
9355  i = nvlbvars-1;
9356  while ( i >= 0 && !(*infeasible) )
9357  {
9358  assert(vlbvars[i] != implvar);
9359  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9360 
9361  /* we have x == varfixing -> y <= b and y >= c*z + d:
9362  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9363  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9364  *
9365  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9366  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9367  * aggregation variable (the one which will stay active);
9368  *
9369  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9370  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9371  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9372  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9373  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9374  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9375  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9376  * have to explicitly check that the active variable has not a variable status
9377  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9378  */
9379  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9380  {
9381  SCIP_Real vbimplbound;
9382 
9383  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9384  if( vlbcoefs[i] >= 0.0 )
9385  {
9386  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9387  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9388  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9389  infeasible, nbdchgs, &added) );
9390  }
9391  else
9392  {
9393  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9394  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9395  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9396  infeasible, nbdchgs, &added) );
9397  }
9398  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9399  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9400  }
9401  --i;
9402  }
9403  }
9404 
9405  /* non-binary variable: variable upper bounds of implvar */
9406  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9407  {
9408  SCIP_VAR** vubvars;
9409  SCIP_Real* vubcoefs;
9410  SCIP_Real* vubconstants;
9411  int nvubvars;
9412  int i;
9413 
9414  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9415  vubvars = SCIPvboundsGetVars(implvar->vubs);
9416  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9417  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9418 
9419  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9420  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9421  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9422  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9423  * is that we add the same implication twice - this does no harm
9424  */
9425  i = nvubvars-1;
9426  while ( i >= 0 && !(*infeasible) )
9427  {
9428  assert(vubvars[i] != implvar);
9429  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9430 
9431  /* we have x == varfixing -> y >= b and y <= c*z + d:
9432  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9433  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9434  *
9435  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9436  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9437  * aggregation variable (the one which will stay active);
9438  *
9439  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9440  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9441  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9442  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9443  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9444  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9445  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9446  * have to explicitly check that the active variable has not a variable status
9447  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9448  */
9449  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9450  {
9451  SCIP_Real vbimplbound;
9452 
9453  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9454  if( vubcoefs[i] >= 0.0 )
9455  {
9456  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9457  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9458  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9459  infeasible, nbdchgs, &added) );
9460  }
9461  else
9462  {
9463  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9464  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9465  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9466  infeasible, nbdchgs, &added) );
9467  }
9468  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9469  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9470  }
9471  --i;
9472  }
9473  }
9474  }
9475 
9476  return SCIP_OKAY;
9477 }
9478 
9479 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9480  * if z is binary, the corresponding valid implication for z is also added;
9481  * improves the global bounds of the variable and the vlb variable if possible
9482  */
9484  SCIP_VAR* var, /**< problem variable */
9485  BMS_BLKMEM* blkmem, /**< block memory */
9486  SCIP_SET* set, /**< global SCIP settings */
9487  SCIP_STAT* stat, /**< problem statistics */
9488  SCIP_PROB* transprob, /**< transformed problem */
9489  SCIP_PROB* origprob, /**< original problem */
9490  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9491  SCIP_REOPT* reopt, /**< reoptimization data structure */
9492  SCIP_LP* lp, /**< current LP data */
9493  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9494  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9495  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9496  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9497  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9498  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9499  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9500  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9501  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9502  )
9503 {
9504  assert(var != NULL);
9505  assert(set != NULL);
9506  assert(var->scip == set->scip);
9507  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9508  assert(infeasible != NULL);
9509 
9510  SCIPdebugMessage("adding variable lower bound <%s> >= %g<%s> + %g\n",
9511  SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9512 
9513  *infeasible = FALSE;
9514  if( nbdchgs != NULL )
9515  *nbdchgs = 0;
9516 
9517  switch( SCIPvarGetStatus(var) )
9518  {
9520  assert(var->data.original.transvar != NULL);
9521  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9522  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9523  break;
9524 
9525  case SCIP_VARSTATUS_COLUMN:
9526  case SCIP_VARSTATUS_LOOSE:
9527  case SCIP_VARSTATUS_FIXED:
9528  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9529  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9530  SCIPdebugMessage(" -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
9531  SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9532 
9533  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9534  if( SCIPsetIsZero(set, vlbcoef) )
9535  {
9536  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9537  *infeasible = TRUE;
9538  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9539  {
9540  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9541  * with the local bound, in this case we need to store the bound change as pending bound change
9542  */
9543  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9544  {
9545  assert(tree != NULL);
9546  assert(transprob != NULL);
9547  assert(SCIPprobIsTransformed(transprob));
9548 
9549  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9550  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9551  }
9552  else
9553  {
9554  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9555  }
9556 
9557  if( nbdchgs != NULL )
9558  (*nbdchgs)++;
9559  }
9560  }
9561  else if( SCIPvarIsActive(vlbvar) )
9562  {
9563  SCIP_Real xlb;
9564  SCIP_Real xub;
9565  SCIP_Real zlb;
9566  SCIP_Real zub;
9567  SCIP_Real minvlb;
9568  SCIP_Real maxvlb;
9569 
9571  assert(vlbcoef != 0.0);
9572 
9573  minvlb = -SCIPsetInfinity(set);
9574  maxvlb = -SCIPsetInfinity(set);
9575 
9576  xlb = SCIPvarGetLbGlobal(var);
9577  xub = SCIPvarGetUbGlobal(var);
9578  zlb = SCIPvarGetLbGlobal(vlbvar);
9579  zub = SCIPvarGetUbGlobal(vlbvar);
9580 
9581  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9582  if( vlbcoef >= 0.0 )
9583  {
9584  SCIP_Real newzub;
9585 
9586  if( !SCIPsetIsInfinity(set, xub) )
9587  {
9588  /* x >= b*z + d -> z <= (x-d)/b */
9589  newzub = (xub - vlbconstant)/vlbcoef;
9590 
9591  /* return if the new bound is less than -infinity */
9592  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9593  return SCIP_OKAY;
9594 
9595  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9596  {
9597  *infeasible = TRUE;
9598  return SCIP_OKAY;
9599  }
9600  if( SCIPsetIsFeasLT(set, newzub, zub) )
9601  {
9602  /* bound might be adjusted due to integrality condition */
9603  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9604 
9605  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9606  * with the local bound, in this case we need to store the bound change as pending bound change
9607  */
9608  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9609  {
9610  assert(tree != NULL);
9611  assert(transprob != NULL);
9612  assert(SCIPprobIsTransformed(transprob));
9613 
9614  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9615  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9616  }
9617  else
9618  {
9619  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9620  }
9621  zub = newzub;
9622 
9623  if( nbdchgs != NULL )
9624  (*nbdchgs)++;
9625  }
9626  maxvlb = vlbcoef * zub + vlbconstant;
9627  if( !SCIPsetIsInfinity(set, -zlb) )
9628  minvlb = vlbcoef * zlb + vlbconstant;
9629  }
9630  else
9631  {
9632  if( !SCIPsetIsInfinity(set, zub) )
9633  maxvlb = vlbcoef * zub + vlbconstant;
9634  if( !SCIPsetIsInfinity(set, -zlb) )
9635  minvlb = vlbcoef * zlb + vlbconstant;
9636  }
9637  }
9638  else
9639  {
9640  SCIP_Real newzlb;
9641 
9642  if( !SCIPsetIsInfinity(set, xub) )
9643  {
9644  /* x >= b*z + d -> z >= (x-d)/b */
9645  newzlb = (xub - vlbconstant)/vlbcoef;
9646 
9647  /* return if the new bound is larger than infinity */
9648  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9649  return SCIP_OKAY;
9650 
9651  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9652  {
9653  *infeasible = TRUE;
9654  return SCIP_OKAY;
9655  }
9656  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9657  {
9658  /* bound might be adjusted due to integrality condition */
9659  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9660 
9661  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9662  * with the local bound, in this case we need to store the bound change as pending bound change
9663  */
9664  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9665  {
9666  assert(tree != NULL);
9667  assert(transprob != NULL);
9668  assert(SCIPprobIsTransformed(transprob));
9669 
9670  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9671  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9672  }
9673  else
9674  {
9675  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9676  }
9677  zlb = newzlb;
9678 
9679  if( nbdchgs != NULL )
9680  (*nbdchgs)++;
9681  }
9682  maxvlb = vlbcoef * zlb + vlbconstant;
9683  if( !SCIPsetIsInfinity(set, zub) )
9684  minvlb = vlbcoef * zub + vlbconstant;
9685  }
9686  else
9687  {
9688  if( !SCIPsetIsInfinity(set, -zlb) )
9689  maxvlb = vlbcoef * zlb + vlbconstant;
9690  if( !SCIPsetIsInfinity(set, zub) )
9691  minvlb = vlbcoef * zub + vlbconstant;
9692  }
9693  }
9694  if( maxvlb < minvlb )
9695  maxvlb = minvlb;
9696 
9697  /* adjust bounds due to integrality of variable */
9698  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9699  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9700 
9701  /* check bounds for feasibility */
9702  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9703  {
9704  *infeasible = TRUE;
9705  return SCIP_OKAY;
9706  }
9707  /* improve global lower bound of variable */
9708  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9709  {
9710  /* bound might be adjusted due to integrality condition */
9711  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9712 
9713  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9714  * with the local bound, in this case we need to store the bound change as pending bound change
9715  */
9716  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9717  {
9718  assert(tree != NULL);
9719  assert(transprob != NULL);
9720  assert(SCIPprobIsTransformed(transprob));
9721 
9722  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9723  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9724  }
9725  else
9726  {
9727  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9728  }
9729  xlb = minvlb;
9730 
9731  if( nbdchgs != NULL )
9732  (*nbdchgs)++;
9733  }
9734  minvlb = xlb;
9735 
9736  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9737  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9738  {
9739  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9740  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9741  */
9742 
9743  assert(!SCIPsetIsInfinity(set, -maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9744 
9745  if( vlbcoef >= 0.0 )
9746  {
9747  vlbcoef = maxvlb - minvlb;
9748  vlbconstant = minvlb;
9749  }
9750  else
9751  {
9752  vlbcoef = minvlb - maxvlb;
9753  vlbconstant = maxvlb;
9754  }
9755  }
9756 
9757  /* add variable bound to the variable bounds list */
9758  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9759  {
9760  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9761  assert(!SCIPsetIsZero(set, vlbcoef));
9762 
9763  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9764  * list, thereby also adding the variable bound (or implication) to the other variable
9765  */
9766  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9767  {
9768  /* add corresponding implication:
9769  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9770  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9771  */
9772  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9773  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9774  infeasible, nbdchgs) );
9775  }
9776  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9777  {
9778  /* add corresponding implication:
9779  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9780  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9781  */
9782  SCIP_Real implbound;
9783  implbound = -vlbconstant/vlbcoef;
9784 
9785  /* tighten the implication bound if the variable is integer */
9786  if( SCIPvarIsIntegral(vlbvar) )
9787  {
9788  if( vlbcoef >= 0 )
9789  implbound = SCIPsetFloor(set, implbound);
9790  else
9791  implbound = SCIPsetCeil(set, implbound);
9792  }
9793  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9794  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
9795  implbound, transitive, infeasible, nbdchgs) );
9796  }
9797  else
9798  {
9799  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
9800  }
9801  }
9802  }
9803  break;
9804 
9806  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
9807  * y <= b/a * z + (d-c)/a, if a < 0
9808  */
9809  assert(var->data.aggregate.var != NULL);
9810  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9811  {
9812  /* a > 0 -> add variable lower bound */
9813  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9814  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9815  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9816  }
9817  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9818  {
9819  /* a < 0 -> add variable upper bound */
9820  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9821  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9822  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9823  }
9824  else
9825  {
9826  SCIPerrorMessage("scalar is zero in aggregation\n");
9827  return SCIP_INVALIDDATA;
9828  }
9829  break;
9830 
9832  /* nothing to do here */
9833  break;
9834 
9836  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
9837  assert(var->negatedvar != NULL);
9839  assert(var->negatedvar->negatedvar == var);
9840  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9841  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
9842  nbdchgs) );
9843  break;
9844 
9845  default:
9846  SCIPerrorMessage("unknown variable status\n");
9847  return SCIP_INVALIDDATA;
9848  }
9849 
9850  return SCIP_OKAY;
9851 }
9852 
9853 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
9854  * if z is binary, the corresponding valid implication for z is also added;
9855  * updates the global bounds of the variable and the vub variable correspondingly
9856  */
9858  SCIP_VAR* var, /**< problem variable */
9859  BMS_BLKMEM* blkmem, /**< block memory */
9860  SCIP_SET* set, /**< global SCIP settings */
9861  SCIP_STAT* stat, /**< problem statistics */
9862  SCIP_PROB* transprob, /**< transformed problem */
9863  SCIP_PROB* origprob, /**< original problem */
9864  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9865  SCIP_REOPT* reopt, /**< reoptimization data structure */
9866  SCIP_LP* lp, /**< current LP data */
9867  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9868  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9869  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9870  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
9871  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
9872  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
9873  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9874  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9875  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9876  )
9877 {
9878  assert(var != NULL);
9879  assert(set != NULL);
9880  assert(var->scip == set->scip);
9881  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
9882  assert(infeasible != NULL);
9883 
9884  SCIPdebugMessage("adding variable upper bound <%s> <= %g<%s> + %g\n",
9885  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9886 
9887  *infeasible = FALSE;
9888  if( nbdchgs != NULL )
9889  *nbdchgs = 0;
9890 
9891  switch( SCIPvarGetStatus(var) )
9892  {
9894  assert(var->data.original.transvar != NULL);
9895  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9896  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
9897  break;
9898 
9899  case SCIP_VARSTATUS_COLUMN:
9900  case SCIP_VARSTATUS_LOOSE:
9901  case SCIP_VARSTATUS_FIXED:
9902  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9903  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
9904  SCIPdebugMessage(" -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
9905  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9906 
9907  /* if the vub coefficient is zero, just update the upper bound of the variable */
9908  if( SCIPsetIsZero(set, vubcoef) )
9909  {
9910  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
9911  *infeasible = TRUE;
9912  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
9913  {
9914  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9915  * with the local bound, in this case we need to store the bound change as pending bound change
9916  */
9917  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9918  {
9919  assert(tree != NULL);
9920  assert(transprob != NULL);
9921  assert(SCIPprobIsTransformed(transprob));
9922 
9923  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9924  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
9925  }
9926  else
9927  {
9928  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
9929  }
9930 
9931  if( nbdchgs != NULL )
9932  (*nbdchgs)++;
9933  }
9934  }
9935  else if( SCIPvarIsActive(vubvar) )
9936  {
9937  SCIP_Real xlb;
9938  SCIP_Real xub;
9939  SCIP_Real zlb;
9940  SCIP_Real zub;
9941  SCIP_Real minvub;
9942  SCIP_Real maxvub;
9943 
9945  assert(vubcoef != 0.0);
9946 
9947  minvub = SCIPsetInfinity(set);
9948  maxvub = SCIPsetInfinity(set);
9949 
9950  xlb = SCIPvarGetLbGlobal(var);
9951  xub = SCIPvarGetUbGlobal(var);
9952  zlb = SCIPvarGetLbGlobal(vubvar);
9953  zub = SCIPvarGetUbGlobal(vubvar);
9954 
9955  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
9956  if( vubcoef >= 0.0 )
9957  {
9958  SCIP_Real newzlb;
9959 
9960  if( !SCIPsetIsInfinity(set, -xlb) )
9961  {
9962  /* x <= b*z + d -> z >= (x-d)/b */
9963  newzlb = (xlb - vubconstant)/vubcoef;
9964  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9965  {
9966  *infeasible = TRUE;
9967  return SCIP_OKAY;
9968  }
9969  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9970  {
9971  /* bound might be adjusted due to integrality condition */
9972  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
9973 
9974  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9975  * with the local bound, in this case we need to store the bound change as pending bound change
9976  */
9977  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9978  {
9979  assert(tree != NULL);
9980  assert(transprob != NULL);
9981  assert(SCIPprobIsTransformed(transprob));
9982 
9983  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9984  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9985  }
9986  else
9987  {
9988  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9989  }
9990  zlb = newzlb;
9991 
9992  if( nbdchgs != NULL )
9993  (*nbdchgs)++;
9994  }
9995  minvub = vubcoef * zlb + vubconstant;
9996  if( !SCIPsetIsInfinity(set, zub) )
9997  maxvub = vubcoef * zub + vubconstant;
9998  }
9999  else
10000  {
10001  if( !SCIPsetIsInfinity(set, zub) )
10002  maxvub = vubcoef * zub + vubconstant;
10003  if( !SCIPsetIsInfinity(set, -zlb) )
10004  minvub = vubcoef * zlb + vubconstant;
10005  }
10006  }
10007  else
10008  {
10009  SCIP_Real newzub;
10010 
10011  if( !SCIPsetIsInfinity(set, -xlb) )
10012  {
10013  /* x <= b*z + d -> z <= (x-d)/b */
10014  newzub = (xlb - vubconstant)/vubcoef;
10015  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10016  {
10017  *infeasible = TRUE;
10018  return SCIP_OKAY;
10019  }
10020  if( SCIPsetIsFeasLT(set, newzub, zub) )
10021  {
10022  /* bound might be adjusted due to integrality condition */
10023  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10024 
10025  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10026  * with the local bound, in this case we need to store the bound change as pending bound change
10027  */
10028  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10029  {
10030  assert(tree != NULL);
10031  assert(transprob != NULL);
10032  assert(SCIPprobIsTransformed(transprob));
10033 
10034  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10035  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10036  }
10037  else
10038  {
10039  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10040  }
10041  zub = newzub;
10042 
10043  if( nbdchgs != NULL )
10044  (*nbdchgs)++;
10045  }
10046  minvub = vubcoef * zub + vubconstant;
10047  if( !SCIPsetIsInfinity(set, -zlb) )
10048  maxvub = vubcoef * zlb + vubconstant;
10049  }
10050  else
10051  {
10052  if( !SCIPsetIsInfinity(set, zub) )
10053  minvub = vubcoef * zub + vubconstant;
10054  if( !SCIPsetIsInfinity(set, -zlb) )
10055  maxvub = vubcoef * zlb + vubconstant;
10056  }
10057 
10058  }
10059  if( minvub > maxvub )
10060  minvub = maxvub;
10061 
10062  /* adjust bounds due to integrality of vub variable */
10063  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10064  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10065 
10066  /* check bounds for feasibility */
10067  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10068  {
10069  *infeasible = TRUE;
10070  return SCIP_OKAY;
10071  }
10072  /* improve global upper bound of variable */
10073  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10074  {
10075  /* bound might be adjusted due to integrality condition */
10076  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10077 
10078  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10079  * with the local bound, in this case we need to store the bound change as pending bound change
10080  */
10081  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10082  {
10083  assert(tree != NULL);
10084  assert(transprob != NULL);
10085  assert(SCIPprobIsTransformed(transprob));
10086 
10087  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10088  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10089  }
10090  else
10091  {
10092  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10093  }
10094  xub = maxvub;
10095 
10096  if( nbdchgs != NULL )
10097  (*nbdchgs)++;
10098  }
10099  maxvub = xub;
10100 
10101  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10102  if( SCIPvarIsBinary(vubvar) )
10103  {
10104  /* b > 0: x <= (maxvub - minvub) * z + minvub
10105  * b < 0: x <= (minvub - maxvub) * z + maxvub
10106  */
10107 
10108  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, minvub));
10109 
10110  if( vubcoef >= 0.0 )
10111  {
10112  vubcoef = maxvub - minvub;
10113  vubconstant = minvub;
10114  }
10115  else
10116  {
10117  vubcoef = minvub - maxvub;
10118  vubconstant = maxvub;
10119  }
10120  }
10121 
10122  /* add variable bound to the variable bounds list */
10123  if( SCIPsetIsFeasLT(set, minvub, xub) )
10124  {
10125  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10126  assert(!SCIPsetIsZero(set, vubcoef));
10127 
10128  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10129  * list, thereby also adding the variable bound (or implication) to the other variable
10130  */
10131  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10132  {
10133  /* add corresponding implication:
10134  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10135  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10136  */
10137  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10138  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10139  infeasible, nbdchgs) );
10140  }
10141  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10142  {
10143  /* add corresponding implication:
10144  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10145  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10146  */
10147  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10148  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10149  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10150  }
10151  else
10152  {
10153  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10154  }
10155  }
10156  }
10157  break;
10158 
10160  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10161  * y >= b/a * z + (d-c)/a, if a < 0
10162  */
10163  assert(var->data.aggregate.var != NULL);
10164  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10165  {
10166  /* a > 0 -> add variable upper bound */
10167  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10168  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10169  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10170  }
10171  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10172  {
10173  /* a < 0 -> add variable lower bound */
10174  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10175  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10176  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10177  }
10178  else
10179  {
10180  SCIPerrorMessage("scalar is zero in aggregation\n");
10181  return SCIP_INVALIDDATA;
10182  }
10183  break;
10184 
10186  /* nothing to do here */
10187  break;
10188 
10190  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10191  assert(var->negatedvar != NULL);
10193  assert(var->negatedvar->negatedvar == var);
10194  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10195  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10196  nbdchgs) );
10197  break;
10198 
10199  default:
10200  SCIPerrorMessage("unknown variable status\n");
10201  return SCIP_INVALIDDATA;
10202  }
10203 
10204  return SCIP_OKAY;
10205 }
10206 
10207 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10208  * also adds the corresponding implication or variable bound to the implied variable;
10209  * if the implication is conflicting, the variable is fixed to the opposite value;
10210  * if the variable is already fixed to the given value, the implication is performed immediately;
10211  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10212  */
10214  SCIP_VAR* var, /**< problem variable */
10215  BMS_BLKMEM* blkmem, /**< block memory */
10216  SCIP_SET* set, /**< global SCIP settings */
10217  SCIP_STAT* stat, /**< problem statistics */
10218  SCIP_PROB* transprob, /**< transformed problem */
10219  SCIP_PROB* origprob, /**< original problem */
10220  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10221  SCIP_REOPT* reopt, /**< reoptimization data structure */
10222  SCIP_LP* lp, /**< current LP data */
10223  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10224  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10225  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10226  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10227  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10228  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10229  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10230  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10231  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10232  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10233  )
10234 {
10235  assert(var != NULL);
10236  assert(set != NULL);
10237  assert(var->scip == set->scip);
10238  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10239  assert(infeasible != NULL);
10240 
10241  *infeasible = FALSE;
10242  if( nbdchgs != NULL )
10243  *nbdchgs = 0;
10244 
10245  switch( SCIPvarGetStatus(var) )
10246  {
10248  assert(var->data.original.transvar != NULL);
10249  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10250  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10251  nbdchgs) );
10252  break;
10253 
10254  case SCIP_VARSTATUS_COLUMN:
10255  case SCIP_VARSTATUS_LOOSE:
10256  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10257  * the variable, the implication can be applied directly;
10258  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10259  */
10260  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10261  {
10262  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10263  {
10264  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10265  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10266  }
10267  }
10268  else
10269  {
10270  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10271  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10272  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10273  {
10274  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10275  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10276  }
10277  }
10278  break;
10279 
10280  case SCIP_VARSTATUS_FIXED:
10281  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10282  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10283  {
10284  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10285  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10286  }
10287  break;
10288 
10290  /* implication added for x == 1:
10291  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10292  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10293  * implication added for x == 0:
10294  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10295  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10296  *
10297  * use only binary variables z
10298  */
10299  assert(var->data.aggregate.var != NULL);
10300  if( SCIPvarIsBinary(var->data.aggregate.var) )
10301  {
10302  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10303  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10304 
10305  if( var->data.aggregate.scalar > 0 )
10306  {
10307  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10308  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10309  nbdchgs) );
10310  }
10311  else
10312  {
10313  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10314  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10315  nbdchgs) );
10316  }
10317  }
10318  break;
10319 
10321  /* nothing to do here */
10322  break;
10323 
10325  /* implication added for x == 1:
10326  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10327  * implication added for x == 0:
10328  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10329  */
10330  assert(var->negatedvar != NULL);
10332  assert(var->negatedvar->negatedvar == var);
10333  assert(SCIPvarIsBinary(var->negatedvar));
10334 
10336  {
10337  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10338  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10339  }
10340  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10341  else
10342  {
10343  /* if the implied variable is of binary type exchange the variables */
10344  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10345  {
10346  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10347  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10348  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10349  infeasible, nbdchgs) );
10350  }
10351  else
10352  {
10353  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10354  * implication as variable bounds
10355  */
10356 
10357  /* add variable lower bound on the negation of var */
10358  if( varfixing )
10359  {
10360  /* (x = 1 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 1), this is done by adding ~x >= b*z + d
10361  * as variable lower bound
10362  */
10363  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10364  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10365  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10366  }
10367  else
10368  {
10369  /* (x = 0 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 0), this is done by adding ~x <= b*z + d
10370  * as variable upper bound
10371  */
10372  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10373  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10374  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10375  }
10376 
10377  /* add variable bound on implvar */
10378  if( impltype == SCIP_BOUNDTYPE_UPPER )
10379  {
10380  /* (z = 1 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 0), this is done by adding z <= b*~x + d
10381  * as variable upper bound
10382  */
10383  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10384  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10385  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10386  }
10387  else
10388  {
10389  /* (z = 0 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 1), this is done by adding z >= b*~x + d
10390  * as variable upper bound
10391  */
10392  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10393  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10394  transitive, infeasible, nbdchgs) );
10395  }
10396  }
10397  }
10398  break;
10399 
10400  default:
10401  SCIPerrorMessage("unknown variable status\n");
10402  return SCIP_INVALIDDATA;
10403  }
10404 
10405  return SCIP_OKAY;
10406 }
10407 
10408 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10409  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10410  * both variables must be active, variable x must be binary
10411  */
10413  SCIP_VAR* var, /**< problem variable x */
10414  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10415  SCIP_VAR* implvar, /**< variable y to search for */
10416  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10417  )
10418 {
10419  assert(var != NULL);
10420  assert(implvar != NULL);
10421  assert(SCIPvarIsActive(var));
10422  assert(SCIPvarIsActive(implvar));
10423  assert(SCIPvarIsBinary(var));
10424 
10425  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10426 }
10427 
10428 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10429  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10430  * both variables must be active binary variables
10431  */
10433  SCIP_VAR* var, /**< problem variable x */
10434  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10435  SCIP_VAR* implvar, /**< variable y to search for */
10436  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10437  )
10438 {
10439  assert(SCIPvarIsBinary(implvar));
10440 
10441  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10442 }
10443 
10444 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10446  SCIP_VAR* var, /**< problem variable */
10447  BMS_BLKMEM* blkmem, /**< block memory */
10448  SCIP_SET* set, /**< global SCIP settings */
10449  SCIP_STAT* stat, /**< problem statistics */
10450  SCIP_PROB* transprob, /**< transformed problem */
10451  SCIP_PROB* origprob, /**< original problem */
10452  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10453  SCIP_REOPT* reopt, /**< reoptimization data structure */
10454  SCIP_LP* lp, /**< current LP data */
10455  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10456  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10457  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10458  SCIP_Bool value, /**< value to fix variable to */
10459  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10460  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10461  )
10462 {
10463  assert(var != NULL);
10464  assert(set != NULL);
10465  assert(var->scip == set->scip);
10466  assert(infeasible != NULL);
10467 
10468  *infeasible = FALSE;
10469 
10470  if( value == FALSE )
10471  {
10472  if( var->glbdom.lb > 0.5 )
10473  *infeasible = TRUE;
10474  else if( var->glbdom.ub > 0.5 )
10475  {
10476  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10477  * with the local bound, in this case we need to store the bound change as pending bound change
10478  */
10479  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10480  {
10481  assert(tree != NULL);
10482  assert(transprob != NULL);
10483  assert(SCIPprobIsTransformed(transprob));
10484 
10485  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10486  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10487  }
10488  else
10489  {
10490  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10491  }
10492 
10493  if( nbdchgs != NULL )
10494  (*nbdchgs)++;
10495  }
10496  }
10497  else
10498  {
10499  if( var->glbdom.ub < 0.5 )
10500  *infeasible = TRUE;
10501  else if( var->glbdom.lb < 0.5 )
10502  {
10503  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10504  * with the local bound, in this case we need to store the bound change as pending bound change
10505  */
10506  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10507  {
10508  assert(tree != NULL);
10509  assert(transprob != NULL);
10510  assert(SCIPprobIsTransformed(transprob));
10511 
10512  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10513  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10514  }
10515  else
10516  {
10517  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10518  }
10519 
10520  if( nbdchgs != NULL )
10521  (*nbdchgs)++;
10522  }
10523  }
10524 
10525  /* during presolving, the variable should have been removed immediately from all its cliques */
10526  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10527 
10528  return SCIP_OKAY;
10529 }
10530 
10531 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10532  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10533  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10534  * the opposite of the value they take in the clique
10535  */
10537  SCIP_VAR* var, /**< problem variable */
10538  BMS_BLKMEM* blkmem, /**< block memory */
10539  SCIP_SET* set, /**< global SCIP settings */
10540  SCIP_STAT* stat, /**< problem statistics */
10541  SCIP_PROB* transprob, /**< transformed problem */
10542  SCIP_PROB* origprob, /**< original problem */
10543  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10544  SCIP_REOPT* reopt, /**< reoptimization data structure */
10545  SCIP_LP* lp, /**< current LP data */
10546  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10547  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10548  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10549  SCIP_Bool value, /**< value of the variable in the clique */
10550  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10551  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10552  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10553  )
10554 {
10555  assert(var != NULL);
10556  assert(set != NULL);
10557  assert(var->scip == set->scip);
10558  assert(SCIPvarIsBinary(var));
10559  assert(infeasible != NULL);
10560 
10561  *infeasible = FALSE;
10562 
10563  /* get corresponding active problem variable */
10564  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10569  assert(SCIPvarIsBinary(var));
10570 
10571  /* only column and loose variables may be member of a clique */
10573  {
10574  SCIP_Bool doubleentry;
10575  SCIP_Bool oppositeentry;
10576 
10577  /* add variable to clique */
10578  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10579 
10580  /* add clique to variable's clique list */
10581  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10582 
10583  /* check consistency of cliquelist */
10584  SCIPcliquelistCheck(var->cliquelist, var);
10585 
10586  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10587  if( doubleentry )
10588  {
10589  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10590  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10591  }
10592 
10593  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10594  * to the opposite of the value they take in the clique
10595  */
10596  if( oppositeentry )
10597  {
10598  SCIP_VAR** vars;
10599  SCIP_Bool* values;
10600  int nvars;
10601  int i;
10602 
10603  nvars = SCIPcliqueGetNVars(clique);
10604  vars = SCIPcliqueGetVars(clique);
10605  values = SCIPcliqueGetValues(clique);
10606  for( i = 0; i < nvars && !(*infeasible); ++i )
10607  {
10608  if( vars[i] == var )
10609  continue;
10610 
10611  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10612  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10613  }
10614  }
10615  }
10616 
10617  return SCIP_OKAY;
10618 }
10619 
10620 /** adds a filled clique to the cliquelists of all corresponding variables */
10622  SCIP_VAR** vars, /**< problem variables */
10623  SCIP_Bool* values, /**< values of the variables in the clique */
10624  int nvars, /**< number of problem variables */
10625  BMS_BLKMEM* blkmem, /**< block memory */
10626  SCIP_SET* set, /**< global SCIP settings */
10627  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10628  )
10629 {
10630  SCIP_VAR* var;
10631  int v;
10632 
10633  assert(vars != NULL);
10634  assert(values != NULL);
10635  assert(nvars > 0);
10636  assert(set != NULL);
10637  assert(blkmem != NULL);
10638  assert(clique != NULL);
10639 
10640  for( v = nvars - 1; v >= 0; --v )
10641  {
10642  var = vars[v];
10643  assert(SCIPvarIsBinary(var));
10645 
10646  /* add clique to variable's clique list */
10647  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10648 
10649  /* check consistency of cliquelist */
10650  SCIPcliquelistCheck(var->cliquelist, var);
10651  }
10652 
10653  return SCIP_OKAY;
10654 }
10655 
10656 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10657  * itself
10658  */
10660  SCIP_VAR* var, /**< problem variable */
10661  BMS_BLKMEM* blkmem, /**< block memory */
10662  SCIP_SET* set, /**< global SCIP settings */
10663  SCIP_Bool value, /**< value of the variable in the clique */
10664  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10665  )
10666 {
10667  assert(var != NULL);
10668  assert(SCIPvarIsBinary(var));
10670 
10671  /* add clique to variable's clique list */
10672  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10673 
10674  return SCIP_OKAY;
10675 }
10676 
10677 
10678 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10679  * itself
10680  */
10682  SCIP_VAR* var, /**< problem variable */
10683  BMS_BLKMEM* blkmem, /**< block memory */
10684  SCIP_Bool value, /**< value of the variable in the clique */
10685  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10686  )
10687 {
10688  assert(var != NULL);
10689  assert(SCIPvarIsBinary(var));
10690 
10691  /* delete clique from variable's clique list */
10692  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10693 
10694  return SCIP_OKAY;
10695 }
10696 
10697 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10699  SCIP_VAR* var, /**< problem variable */
10700  BMS_BLKMEM* blkmem, /**< block memory */
10701  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10702  SCIP_Bool value, /**< value of the variable in the clique */
10703  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10704  )
10705 {
10706  assert(var != NULL);
10707  assert(SCIPvarIsBinary(var));
10708 
10709  /* get corresponding active problem variable */
10710  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10715  assert(SCIPvarIsBinary(var));
10716 
10717  /* only column and loose variables may be member of a clique */
10719  {
10720  /* delete clique from variable's clique list */
10721  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10722 
10723  /* delete variable from clique */
10724  SCIPcliqueDelVar(clique, cliquetable, var, value);
10725 
10726  /* check consistency of cliquelist */
10727  SCIPcliquelistCheck(var->cliquelist, var);
10728  }
10729 
10730  return SCIP_OKAY;
10731 }
10732 
10733 /** returns whether there is a clique that contains both given variable/value pairs;
10734  * the variables must be active binary variables;
10735  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10736  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10737  *
10738  * @note a variable with it's negated variable are NOT! in a clique
10739  * @note a variable with itself are in a clique
10740  */
10742  SCIP_VAR* var1, /**< first variable */
10743  SCIP_Bool value1, /**< value of first variable */
10744  SCIP_VAR* var2, /**< second variable */
10745  SCIP_Bool value2, /**< value of second variable */
10746  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10747  )
10748 {
10749  assert(var1 != NULL);
10750  assert(var2 != NULL);
10751  assert(SCIPvarIsActive(var1));
10752  assert(SCIPvarIsActive(var2));
10753  assert(SCIPvarIsBinary(var1));
10754  assert(SCIPvarIsBinary(var2));
10755 
10756  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10757  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10758 }
10759 
10760 /** actually changes the branch factor of the variable and of all parent variables */
10761 static
10763  SCIP_VAR* var, /**< problem variable */
10764  SCIP_SET* set, /**< global SCIP settings */
10765  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10766  )
10767 {
10768  SCIP_VAR* parentvar;
10769  SCIP_Real eps;
10770  int i;
10771 
10772  assert(var != NULL);
10773  assert(set != NULL);
10774  assert(var->scip == set->scip);
10775 
10776  /* only use positive values */
10777  eps = SCIPsetEpsilon(set);
10778  branchfactor = MAX(branchfactor, eps);
10779 
10780  SCIPdebugMessage("process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10781 
10782  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10783  return SCIP_OKAY;
10784 
10785  /* change the branch factor */
10786  var->branchfactor = branchfactor;
10787 
10788  /* process parent variables */
10789  for( i = 0; i < var->nparentvars; ++i )
10790  {
10791  parentvar = var->parentvars[i];
10792  assert(parentvar != NULL);
10793 
10794  switch( SCIPvarGetStatus(parentvar) )
10795  {
10797  /* do not change priorities across the border between transformed and original problem */
10798  break;
10799 
10800  case SCIP_VARSTATUS_COLUMN:
10801  case SCIP_VARSTATUS_LOOSE:
10802  case SCIP_VARSTATUS_FIXED:
10804  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10805  SCIPABORT();
10806  return SCIP_INVALIDDATA; /*lint !e527*/
10807 
10810  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
10811  break;
10812 
10813  default:
10814  SCIPerrorMessage("unknown variable status\n");
10815  SCIPABORT();
10816  return SCIP_ERROR; /*lint !e527*/
10817  }
10818  }
10819 
10820  return SCIP_OKAY;
10821 }
10822 
10823 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
10824  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
10825  */
10827  SCIP_VAR* var, /**< problem variable */
10828  SCIP_SET* set, /**< global SCIP settings */
10829  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10830  )
10831 {
10832  int v;
10833 
10834  assert(var != NULL);
10835  assert(set != NULL);
10836  assert(var->scip == set->scip);
10837  assert(branchfactor >= 0.0);
10838 
10839  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
10840 
10841  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
10842  return SCIP_OKAY;
10843 
10844  /* change priorities of attached variables */
10845  switch( SCIPvarGetStatus(var) )
10846  {
10848  if( var->data.original.transvar != NULL )
10849  {
10850  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
10851  }
10852  else
10853  {
10854  assert(set->stage == SCIP_STAGE_PROBLEM);
10855  var->branchfactor = branchfactor;
10856  }
10857  break;
10858 
10859  case SCIP_VARSTATUS_COLUMN:
10860  case SCIP_VARSTATUS_LOOSE:
10861  case SCIP_VARSTATUS_FIXED:
10862  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
10863  break;
10864 
10866  assert(var->data.aggregate.var != NULL);
10867  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
10868  break;
10869 
10871  assert(!var->donotmultaggr);
10872  for( v = 0; v < var->data.multaggr.nvars; ++v )
10873  {
10874  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
10875  }
10876  break;
10877 
10879  assert(var->negatedvar != NULL);
10881  assert(var->negatedvar->negatedvar == var);
10882  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
10883  break;
10884 
10885  default:
10886  SCIPerrorMessage("unknown variable status\n");
10887  SCIPABORT();
10888  return SCIP_ERROR; /*lint !e527*/
10889  }
10890 
10891  return SCIP_OKAY;
10892 }
10893 
10894 /** actually changes the branch priority of the variable and of all parent variables */
10895 static
10897  SCIP_VAR* var, /**< problem variable */
10898  int branchpriority /**< branching priority of the variable */
10899  )
10900 {
10901  SCIP_VAR* parentvar;
10902  int i;
10903 
10904  assert(var != NULL);
10905 
10906  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
10907  var->name, var->branchpriority, branchpriority);
10908 
10909  if( branchpriority == var->branchpriority )
10910  return SCIP_OKAY;
10911 
10912  /* change the branch priority */
10913  var->branchpriority = branchpriority;
10914 
10915  /* process parent variables */
10916  for( i = 0; i < var->nparentvars; ++i )
10917  {
10918  parentvar = var->parentvars[i];
10919  assert(parentvar != NULL);
10920 
10921  switch( SCIPvarGetStatus(parentvar) )
10922  {
10924  /* do not change priorities across the border between transformed and original problem */
10925  break;
10926 
10927  case SCIP_VARSTATUS_COLUMN:
10928  case SCIP_VARSTATUS_LOOSE:
10929  case SCIP_VARSTATUS_FIXED:
10931  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10932  SCIPABORT();
10933  return SCIP_INVALIDDATA; /*lint !e527*/
10934 
10937  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
10938  break;
10939 
10940  default:
10941  SCIPerrorMessage("unknown variable status\n");
10942  return SCIP_ERROR;
10943  }
10944  }
10945 
10946  return SCIP_OKAY;
10947 }
10948 
10949 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
10950  * with lower priority in selection of branching variable
10951  */
10953  SCIP_VAR* var, /**< problem variable */
10954  int branchpriority /**< branching priority of the variable */
10955  )
10956 {
10957  int v;
10958 
10959  assert(var != NULL);
10960 
10961  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
10962 
10963  if( var->branchpriority == branchpriority )
10964  return SCIP_OKAY;
10965 
10966  /* change priorities of attached variables */
10967  switch( SCIPvarGetStatus(var) )
10968  {
10970  if( var->data.original.transvar != NULL )
10971  {
10972  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
10973  }
10974  else
10975  var->branchpriority = branchpriority;
10976  break;
10977 
10978  case SCIP_VARSTATUS_COLUMN:
10979  case SCIP_VARSTATUS_LOOSE:
10980  case SCIP_VARSTATUS_FIXED:
10981  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
10982  break;
10983 
10985  assert(var->data.aggregate.var != NULL);
10986  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
10987  break;
10988 
10990  assert(!var->donotmultaggr);
10991  for( v = 0; v < var->data.multaggr.nvars; ++v )
10992  {
10993  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
10994  }
10995  break;
10996 
10998  assert(var->negatedvar != NULL);
11000  assert(var->negatedvar->negatedvar == var);
11001  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11002  break;
11003 
11004  default:
11005  SCIPerrorMessage("unknown variable status\n");
11006  SCIPABORT();
11007  return SCIP_ERROR; /*lint !e527*/
11008  }
11009 
11010  return SCIP_OKAY;
11011 }
11012 
11013 /** actually changes the branch direction of the variable and of all parent variables */
11014 static
11016  SCIP_VAR* var, /**< problem variable */
11017  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11018  )
11019 {
11020  SCIP_VAR* parentvar;
11021  int i;
11022 
11023  assert(var != NULL);
11024 
11025  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11026  var->name, var->branchdirection, branchdirection);
11027 
11028  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11029  return SCIP_OKAY;
11030 
11031  /* change the branch direction */
11032  var->branchdirection = branchdirection; /*lint !e641*/
11033 
11034  /* process parent variables */
11035  for( i = 0; i < var->nparentvars; ++i )
11036  {
11037  parentvar = var->parentvars[i];
11038  assert(parentvar != NULL);
11039 
11040  switch( SCIPvarGetStatus(parentvar) )
11041  {
11043  /* do not change directions across the border between transformed and original problem */
11044  break;
11045 
11046  case SCIP_VARSTATUS_COLUMN:
11047  case SCIP_VARSTATUS_LOOSE:
11048  case SCIP_VARSTATUS_FIXED:
11050  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11051  SCIPABORT();
11052  return SCIP_INVALIDDATA; /*lint !e527*/
11053 
11055  if( parentvar->data.aggregate.scalar > 0.0 )
11056  {
11057  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11058  }
11059  else
11060  {
11061  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11062  }
11063  break;
11064 
11066  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11067  break;
11068 
11069  default:
11070  SCIPerrorMessage("unknown variable status\n");
11071  SCIPABORT();
11072  return SCIP_ERROR; /*lint !e527*/
11073  }
11074  }
11075 
11076  return SCIP_OKAY;
11077 }
11078 
11079 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11080  * with lower direction in selection of branching variable
11081  */
11083  SCIP_VAR* var, /**< problem variable */
11084  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11085  )
11086 {
11087  int v;
11088 
11089  assert(var != NULL);
11090 
11091  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11092 
11093  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11094  return SCIP_OKAY;
11095 
11096  /* change directions of attached variables */
11097  switch( SCIPvarGetStatus(var) )
11098  {
11100  if( var->data.original.transvar != NULL )
11101  {
11102  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11103  }
11104  else
11105  var->branchdirection = branchdirection; /*lint !e641*/
11106  break;
11107 
11108  case SCIP_VARSTATUS_COLUMN:
11109  case SCIP_VARSTATUS_LOOSE:
11110  case SCIP_VARSTATUS_FIXED:
11111  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11112  break;
11113 
11115  assert(var->data.aggregate.var != NULL);
11116  if( var->data.aggregate.scalar > 0.0 )
11117  {
11118  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11119  }
11120  else
11121  {
11123  }
11124  break;
11125 
11127  assert(!var->donotmultaggr);
11128  for( v = 0; v < var->data.multaggr.nvars; ++v )
11129  {
11130  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11131  assert(var->data.multaggr.vars[v] != NULL);
11133  {
11134  if( var->data.multaggr.scalars[v] > 0.0 )
11135  {
11136  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11137  }
11138  else
11139  {
11141  }
11142  }
11143  }
11144  break;
11145 
11147  assert(var->negatedvar != NULL);
11149  assert(var->negatedvar->negatedvar == var);
11151  break;
11152 
11153  default:
11154  SCIPerrorMessage("unknown variable status\n");
11155  SCIPABORT();
11156  return SCIP_ERROR; /*lint !e527*/
11157  }
11158 
11159  return SCIP_OKAY;
11160 }
11161 
11162 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11163  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11164  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11165  * are equal, which means both variables are equal
11166  */
11168  SCIP_VAR* var1, /**< first problem variable */
11169  SCIP_VAR* var2 /**< second problem variable */
11170  )
11171 {
11172  assert(var1 != NULL);
11173  assert(var2 != NULL);
11176 
11178  var1 = SCIPvarGetNegatedVar(var1);
11180  var2 = SCIPvarGetNegatedVar(var2);
11181 
11182  assert(var1 != NULL);
11183  assert(var2 != NULL);
11184 
11185  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11186  return -1;
11187  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11188  return +1;
11189 
11190  assert(var1 == var2);
11191  return 0;
11192 }
11193 
11194 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11195  * variables are handled as the same variables
11196  */
11197 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11199  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11200 }
11201 
11202 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11203  * variable index; returns 0 if both indices are equal, which means both variables are equal
11204  */
11205 int SCIPvarCompare(
11206  SCIP_VAR* var1, /**< first problem variable */
11207  SCIP_VAR* var2 /**< second problem variable */
11208  )
11209 {
11210  assert(var1 != NULL);
11211  assert(var2 != NULL);
11212 
11213  if( var1->index < var2->index )
11214  return -1;
11215  else if( var1->index > var2->index )
11216  return +1;
11217  else
11218  {
11219  assert(var1 == var2);
11220  return 0;
11221  }
11222 }
11223 
11224 /** comparison method for sorting variables by non-decreasing index */
11225 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11227  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11228 }
11229 
11230 /** comparison method for sorting variables by non-decreasing objective coefficient */
11231 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11233  SCIP_Real obj1;
11234  SCIP_Real obj2;
11235 
11236  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11237  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11238 
11239  if( obj1 < obj2 )
11240  return -1;
11241  else if( obj1 > obj2 )
11242  return +1;
11243  else
11244  return 0;
11245 }
11246 
11247 /** hash key retrieval function for variables */
11248 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11249 { /*lint --e{715}*/
11250  return elem;
11251 }
11252 
11253 /** returns TRUE iff the indices of both variables are equal */
11254 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11255 { /*lint --e{715}*/
11256  if( key1 == key2 )
11257  return TRUE;
11258  return FALSE;
11259 }
11260 
11261 /** returns the hash value of the key */
11262 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11263 { /*lint --e{715}*/
11264  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11265  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11266 }
11267 
11268 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11270  SCIP_SET* set, /**< global SCIP settings */
11271  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11272  * variables, if enough slots exist
11273  */
11274  int* nvars, /**< number of given variables, and as output number of active variables,
11275  * if enough slots exist
11276  */
11277  int varssize, /**< available slots in vars array */
11278  int* requiredsize /**< pointer to store the required array size for the active variables */
11279  )
11280 {
11281  SCIP_VAR** activevars;
11282  int nactivevars;
11283  int activevarssize;
11284 
11285  SCIP_VAR* var;
11286  int v;
11287 
11288  SCIP_VAR** tmpvars;
11289  SCIP_VAR** multvars;
11290  int tmpvarssize;
11291  int ntmpvars;
11292  int noldtmpvars;
11293  int nmultvars;
11294 
11295  assert(set != NULL);
11296  assert(nvars != NULL);
11297  assert(vars != NULL || *nvars == 0);
11298  assert(varssize >= *nvars);
11299  assert(requiredsize != NULL);
11300 
11301  *requiredsize = 0;
11302 
11303  if( *nvars == 0 )
11304  return SCIP_OKAY;
11305 
11306  nactivevars = 0;
11307  activevarssize = *nvars;
11308  ntmpvars = *nvars;
11309  tmpvarssize = *nvars;
11310 
11311  /* temporary memory */
11312  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11313  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11314 
11315  noldtmpvars = ntmpvars;
11316 
11317  /* sort all variables to combine equal variables easily */
11318  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11319  for( v = ntmpvars - 1; v > 0; --v )
11320  {
11321  /* combine same variables */
11322  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11323  {
11324  --ntmpvars;
11325  tmpvars[v] = tmpvars[ntmpvars];
11326  }
11327  }
11328  /* sort all variables again to combine equal variables later on */
11329  if( noldtmpvars > ntmpvars )
11330  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11331 
11332  /* collect for each variable the representation in active variables */
11333  while( ntmpvars >= 1 )
11334  {
11335  --ntmpvars;
11336  var = tmpvars[ntmpvars];
11337  assert( var != NULL );
11338 
11339  switch( SCIPvarGetStatus(var) )
11340  {
11342  if( var->data.original.transvar == NULL )
11343  {
11344  SCIPerrorMessage("original variable has no transformed variable attached\n");
11345  SCIPABORT();
11346  return SCIP_INVALIDDATA; /*lint !e527*/
11347  }
11348  tmpvars[ntmpvars] = var->data.original.transvar;
11349  ++ntmpvars;
11350  break;
11351 
11353  tmpvars[ntmpvars] = var->data.aggregate.var;
11354  ++ntmpvars;
11355  break;
11356 
11358  tmpvars[ntmpvars] = var->negatedvar;
11359  ++ntmpvars;
11360  break;
11361 
11362  case SCIP_VARSTATUS_LOOSE:
11363  case SCIP_VARSTATUS_COLUMN:
11364  /* check for space in temporary memory */
11365  if( nactivevars >= activevarssize )
11366  {
11367  activevarssize *= 2;
11368  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11369  assert(nactivevars < activevarssize);
11370  }
11371  activevars[nactivevars] = var;
11372  nactivevars++;
11373  break;
11374 
11376  /* x = a_1*y_1 + ... + a_n*y_n + c */
11377  nmultvars = var->data.multaggr.nvars;
11378  multvars = var->data.multaggr.vars;
11379 
11380  /* check for space in temporary memory */
11381  if( nmultvars + ntmpvars > tmpvarssize )
11382  {
11383  while( nmultvars + ntmpvars > tmpvarssize )
11384  tmpvarssize *= 2;
11385  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11386  assert(nmultvars + ntmpvars <= tmpvarssize);
11387  }
11388 
11389  /* copy all multi-aggregation variables into our working array */
11390  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11391 
11392  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11393  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11394 
11395  ntmpvars += nmultvars;
11396  noldtmpvars = ntmpvars;
11397 
11398  /* sort all variables to combine equal variables easily */
11399  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11400  for( v = ntmpvars - 1; v > 0; --v )
11401  {
11402  /* combine same variables */
11403  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11404  {
11405  --ntmpvars;
11406  tmpvars[v] = tmpvars[ntmpvars];
11407  }
11408  }
11409  /* sort all variables again to combine equal variables later on */
11410  if( noldtmpvars > ntmpvars )
11411  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11412 
11413  break;
11414 
11415  case SCIP_VARSTATUS_FIXED:
11416  /* no need for memorizing fixed variables */
11417  break;
11418 
11419  default:
11420  SCIPerrorMessage("unknown variable status\n");
11421  SCIPABORT();
11422  return SCIP_INVALIDDATA; /*lint !e527*/
11423  }
11424  }
11425 
11426  /* sort variable array by variable index */
11427  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11428 
11429  /* eliminate duplicates and count required size */
11430  v = nactivevars - 1;
11431  while( v > 0 )
11432  {
11433  /* combine both variable since they are the same */
11434  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11435  {
11436  --nactivevars;
11437  activevars[v] = activevars[nactivevars];
11438  }
11439  --v;
11440  }
11441  *requiredsize = nactivevars;
11442 
11443  if( varssize >= *requiredsize )
11444  {
11445  assert(vars != NULL);
11446 
11447  *nvars = *requiredsize;
11448  BMScopyMemoryArray(vars, activevars, nactivevars);
11449  }
11450 
11451  SCIPsetFreeBufferArray(set, &tmpvars);
11452  SCIPsetFreeBufferArray(set, &activevars);
11453 
11454  return SCIP_OKAY;
11455 }
11456 
11457 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11458  * @note the content of the given array will/might change
11459  */
11460 void SCIPvarsGetProbvar(
11461  SCIP_VAR** vars, /**< array of problem variables */
11462  int nvars /**< number of variables */
11463  )
11464 {
11465  int v;
11466 
11467  assert(vars != NULL || nvars == 0);
11468 
11469  for( v = nvars - 1; v >= 0; --v )
11470  {
11471  assert(vars != NULL);
11472  assert(vars[v] != NULL);
11473 
11474  vars[v] = SCIPvarGetProbvar(vars[v]);
11475  assert(vars[v] != NULL);
11476  }
11477 }
11478 
11479 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11481  SCIP_VAR* var /**< problem variable */
11482  )
11483 {
11484  SCIP_VAR* retvar;
11485 
11486  assert(var != NULL);
11487 
11488  retvar = var;
11489 
11490  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11491 
11492  while( TRUE ) /*lint !e716 */
11493  {
11494  assert(retvar != NULL);
11495 
11496  switch( SCIPvarGetStatus(retvar) )
11497  {
11499  if( retvar->data.original.transvar == NULL )
11500  {
11501  SCIPerrorMessage("original variable has no transformed variable attached\n");
11502  SCIPABORT();
11503  return NULL; /*lint !e527 */
11504  }
11505  retvar = retvar->data.original.transvar;
11506  break;
11507 
11508  case SCIP_VARSTATUS_LOOSE:
11509  case SCIP_VARSTATUS_COLUMN:
11510  case SCIP_VARSTATUS_FIXED:
11511  return retvar;
11512 
11514  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11515  if ( retvar->data.multaggr.nvars == 1 )
11516  retvar = retvar->data.multaggr.vars[0];
11517  else
11518  return retvar;
11519  break;
11520 
11522  retvar = retvar->data.aggregate.var;
11523  break;
11524 
11526  retvar = retvar->negatedvar;
11527  break;
11528 
11529  default:
11530  SCIPerrorMessage("unknown variable status\n");
11531  SCIPABORT();
11532  return NULL; /*lint !e527*/
11533  }
11534  }
11535 }
11536 
11537 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11538  * negation status of each variable
11539  */
11541  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11542  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11543  int nvars /**< number of variables and values in vars and negated array */
11544  )
11545 {
11546  SCIP_VAR** var;
11547  SCIP_Bool* negated;
11548  int v;
11549 
11550  assert(vars != NULL);
11551  assert(*vars != NULL || nvars == 0);
11552  assert(negatedarr != NULL);
11553  assert(*negatedarr != NULL || nvars == 0);
11554 
11555  for( v = nvars - 1; v >= 0; --v )
11556  {
11557  var = &((*vars)[v]);
11558  negated = &((*negatedarr)[v]);
11559 
11560  /* get problem variable */
11561  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11562  }
11563 
11564  return SCIP_OKAY;
11565 }
11566 
11567 
11568 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11569  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11570  * FALSE is used)
11571  */
11573  SCIP_VAR** var, /**< pointer to binary problem variable */
11574  SCIP_Bool* negated /**< pointer to update the negation status */
11575  )
11576 {
11577  SCIP_Bool active = FALSE;
11578 #ifndef NDEBUG
11579  SCIP_Real constant = 0.0;
11580  SCIP_Bool orignegated = *negated;
11581 #endif
11582 
11583  assert(var != NULL);
11584  assert(*var != NULL);
11585  assert(negated != NULL);
11586  assert(SCIPvarIsBinary(*var));
11587 
11588  while( !active && *var != NULL )
11589  {
11590  switch( SCIPvarGetStatus(*var) )
11591  {
11593  if( (*var)->data.original.transvar == NULL )
11594  return SCIP_OKAY;
11595  *var = (*var)->data.original.transvar;
11596  break;
11597 
11598  case SCIP_VARSTATUS_LOOSE:
11599  case SCIP_VARSTATUS_COLUMN:
11600  case SCIP_VARSTATUS_FIXED:
11601  active = TRUE;
11602  break;
11603 
11605  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11606  if ( (*var)->data.multaggr.nvars == 1 )
11607  {
11608  assert( (*var)->data.multaggr.vars != NULL );
11609  assert( (*var)->data.multaggr.scalars != NULL );
11610  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11611  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11612 
11613  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11614  * another variable which needs to be fixed
11615  *
11616  * e.g. x = y - 1 => (x = 0 && y = 1)
11617  * e.g. x = y + 1 => (x = 1 && y = 0)
11618  *
11619  * is this special case we need to return the muti-aggregation
11620  */
11621  if( EPSEQ((*var)->data.multaggr.constant, -1.0, 1e-06) || (EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) && EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06)) )
11622  {
11623  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11624  }
11625  else
11626  {
11627  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11628  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11629  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11630  * we will return the aggregated variable;
11631  */
11632  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11633  {
11634  active = TRUE;
11635  break;
11636  }
11637 
11638  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11639  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11640  * so if this is the case, we will return the aggregated variable
11641  */
11642  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11643  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11644  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11645 
11646  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11647  {
11648  active = TRUE;
11649  break;
11650  }
11651 
11652  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11653 
11654  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11655  {
11656  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11657  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11658  * variable itself is multi-aggregated again?
11659  */
11660  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11661  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11662  SCIPvarGetNLocksUp((*var)->data.multaggr.vars[0]) > 0) : TRUE);
11663  }
11664  else
11665  {
11666  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11667 #ifndef NDEBUG
11668  constant += (*negated) != orignegated ? -1.0 : 1.0;
11669 #endif
11670 
11671  *negated = !(*negated);
11672  }
11673  *var = (*var)->data.multaggr.vars[0];
11674  break;
11675  }
11676  }
11677  active = TRUE;
11678  break;
11679 
11680  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11681  assert((*var)->data.aggregate.var != NULL);
11682  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11683  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11684 #ifndef NDEBUG
11685  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11686 #endif
11687 
11688  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11689  *var = (*var)->data.aggregate.var;
11690  break;
11691 
11692  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11693  assert((*var)->negatedvar != NULL);
11694 #ifndef NDEBUG
11695  constant += (*negated) != orignegated ? -1.0 : 1.0;
11696 #endif
11697 
11698  *negated = !(*negated);
11699  *var = (*var)->negatedvar;
11700  break;
11701 
11702  default:
11703  SCIPerrorMessage("unknown variable status\n");
11704  return SCIP_INVALIDDATA;
11705  }
11706  }
11707  assert(active == (*var != NULL));
11708 
11709  if( active )
11710  {
11711  assert(SCIPvarIsBinary(*var));
11712  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11713  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11714 
11715  return SCIP_OKAY;
11716  }
11717  else
11718  {
11719  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11720  return SCIP_INVALIDDATA;
11721  }
11722 }
11723 
11724 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11725  * values
11726  */
11728  SCIP_VAR** var, /**< pointer to problem variable */
11729  SCIP_Real* bound, /**< pointer to bound value to transform */
11730  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11731  )
11732 {
11733  assert(var != NULL);
11734  assert(*var != NULL);
11735  assert(bound != NULL);
11736  assert(boundtype != NULL);
11737 
11738  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11739 
11740  switch( SCIPvarGetStatus(*var) )
11741  {
11743  if( (*var)->data.original.transvar == NULL )
11744  {
11745  SCIPerrorMessage("original variable has no transformed variable attached\n");
11746  return SCIP_INVALIDDATA;
11747  }
11748  *var = (*var)->data.original.transvar;
11749  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11750  break;
11751 
11752  case SCIP_VARSTATUS_LOOSE:
11753  case SCIP_VARSTATUS_COLUMN:
11754  case SCIP_VARSTATUS_FIXED:
11755  break;
11756 
11758  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11759  if ( (*var)->data.multaggr.nvars == 1 )
11760  {
11761  assert( (*var)->data.multaggr.vars != NULL );
11762  assert( (*var)->data.multaggr.scalars != NULL );
11763  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11764 
11765  (*bound) /= (*var)->data.multaggr.scalars[0];
11766  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11767  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11768  {
11769  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11770  *boundtype = SCIP_BOUNDTYPE_UPPER;
11771  else
11772  *boundtype = SCIP_BOUNDTYPE_LOWER;
11773  }
11774  *var = (*var)->data.multaggr.vars[0];
11775  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11776  }
11777  break;
11778 
11779  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11780  assert((*var)->data.aggregate.var != NULL);
11781  assert((*var)->data.aggregate.scalar != 0.0);
11782 
11783  (*bound) /= (*var)->data.aggregate.scalar;
11784  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11785  if( (*var)->data.aggregate.scalar < 0.0 )
11786  {
11787  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11788  *boundtype = SCIP_BOUNDTYPE_UPPER;
11789  else
11790  *boundtype = SCIP_BOUNDTYPE_LOWER;
11791  }
11792  *var = (*var)->data.aggregate.var;
11793  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11794  break;
11795 
11796  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11797  assert((*var)->negatedvar != NULL);
11798  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11799  assert((*var)->negatedvar->negatedvar == *var);
11800  (*bound) = (*var)->data.negate.constant - *bound;
11801  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11802  *boundtype = SCIP_BOUNDTYPE_UPPER;
11803  else
11804  *boundtype = SCIP_BOUNDTYPE_LOWER;
11805  *var = (*var)->negatedvar;
11806  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11807  break;
11808 
11809  default:
11810  SCIPerrorMessage("unknown variable status\n");
11811  return SCIP_INVALIDDATA;
11812  }
11813 
11814  return SCIP_OKAY;
11815 }
11816 
11817 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
11818  * values
11819  */
11821  SCIP_VAR** var, /**< pointer to problem variable */
11822  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
11823  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
11824  )
11825 {
11826  assert(var != NULL);
11827  assert(*var != NULL);
11828  assert(left != NULL);
11829  assert(right != NULL);
11830 
11831  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
11832 
11833  switch( SCIPvarGetStatus(*var) )
11834  {
11836  if( (*var)->data.original.transvar == NULL )
11837  {
11838  SCIPerrorMessage("original variable has no transformed variable attached\n");
11839  return SCIP_INVALIDDATA;
11840  }
11841  *var = (*var)->data.original.transvar;
11842  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11843  break;
11844 
11845  case SCIP_VARSTATUS_LOOSE:
11846  case SCIP_VARSTATUS_COLUMN:
11847  case SCIP_VARSTATUS_FIXED:
11849  break;
11850 
11851  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11852  assert((*var)->data.aggregate.var != NULL);
11853  assert((*var)->data.aggregate.scalar != 0.0);
11854 
11855  /* scale back */
11856  (*left) /= (*var)->data.aggregate.scalar;
11857  (*right) /= (*var)->data.aggregate.scalar;
11858 
11859  /* shift back */
11860  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11861  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11862 
11863  *var = (*var)->data.aggregate.var;
11864 
11865  /* check if the interval bounds have to swapped */
11866  if( (*var)->data.aggregate.scalar < 0.0 )
11867  {
11868  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11869  }
11870  else
11871  {
11872  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11873  }
11874  break;
11875 
11876  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11877  assert((*var)->negatedvar != NULL);
11878  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11879  assert((*var)->negatedvar->negatedvar == *var);
11880 
11881  /* shift and scale back */
11882  (*left) = (*var)->data.negate.constant - (*left);
11883  (*right) = (*var)->data.negate.constant - (*right);
11884 
11885  *var = (*var)->negatedvar;
11886 
11887  /* through the negated variable the left and right interval bound have to swapped */
11888  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11889  break;
11890 
11891  default:
11892  SCIPerrorMessage("unknown variable status\n");
11893  return SCIP_INVALIDDATA;
11894  }
11895 
11896  return SCIP_OKAY;
11897 }
11898 
11899 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
11900  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
11901  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
11902  * with only one active variable (this can happen due to fixings after the multi-aggregation),
11903  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
11904  */
11906  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
11907  SCIP_SET* set, /**< global SCIP settings */
11908  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
11909  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
11910  )
11911 {
11912  assert(var != NULL);
11913  assert(scalar != NULL);
11914  assert(constant != NULL);
11915 
11916  while( *var != NULL )
11917  {
11918  switch( SCIPvarGetStatus(*var) )
11919  {
11921  if( (*var)->data.original.transvar == NULL )
11922  {
11923  SCIPerrorMessage("original variable has no transformed variable attached\n");
11924  return SCIP_INVALIDDATA;
11925  }
11926  *var = (*var)->data.original.transvar;
11927  break;
11928 
11929  case SCIP_VARSTATUS_LOOSE:
11930  case SCIP_VARSTATUS_COLUMN:
11931  return SCIP_OKAY;
11932 
11933  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
11934  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11935  {
11936  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
11937  {
11938  assert(*scalar != 0.0);
11939  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
11940  (*constant) = SCIPsetInfinity(set);
11941  else
11942  (*constant) = -SCIPsetInfinity(set);
11943  }
11944  else
11945  (*constant) += *scalar * (*var)->glbdom.lb;
11946  }
11947 #ifndef NDEBUG
11948  else
11949  {
11950  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
11951  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11952  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
11953  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11954  }
11955 #endif
11956  *scalar = 0.0;
11957  return SCIP_OKAY;
11958 
11960  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11961  if ( (*var)->data.multaggr.nvars == 1 )
11962  {
11963  assert((*var)->data.multaggr.vars != NULL);
11964  assert((*var)->data.multaggr.scalars != NULL);
11965  assert((*var)->data.multaggr.vars[0] != NULL);
11966  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11967  {
11968  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
11969  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
11970  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
11971  */
11972  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
11973  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
11974  {
11975  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
11976  {
11977  assert(!SCIPsetIsInfinity(set, -(*constant)));
11978  (*constant) = SCIPsetInfinity(set);
11979  }
11980  else
11981  {
11982  assert(!SCIPsetIsInfinity(set, *constant));
11983  (*constant) = -SCIPsetInfinity(set);
11984  }
11985  (*scalar) = 0.0;
11986  }
11987  else
11988  (*constant) += *scalar * (*var)->data.multaggr.constant;
11989  }
11990  (*scalar) *= (*var)->data.multaggr.scalars[0];
11991  *var = (*var)->data.multaggr.vars[0];
11992  break;
11993  }
11994  return SCIP_OKAY;
11995 
11996  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11997  assert((*var)->data.aggregate.var != NULL);
11998  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
11999  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12000  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12001  (*constant) += *scalar * (*var)->data.aggregate.constant;
12002  (*scalar) *= (*var)->data.aggregate.scalar;
12003  *var = (*var)->data.aggregate.var;
12004  break;
12005 
12006  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12007  assert((*var)->negatedvar != NULL);
12008  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12009  assert((*var)->negatedvar->negatedvar == *var);
12010  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12011  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12012  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12013  (*constant) += *scalar * (*var)->data.negate.constant;
12014  (*scalar) *= -1.0;
12015  *var = (*var)->negatedvar;
12016  break;
12017 
12018  default:
12019  SCIPerrorMessage("unknown variable status\n");
12020  SCIPABORT();
12021  return SCIP_INVALIDDATA; /*lint !e527*/
12022  }
12023  }
12024  *scalar = 0.0;
12025 
12026  return SCIP_OKAY;
12027 }
12028 
12029 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12030  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12031  */
12033  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12034  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12035  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12036  )
12037 {
12038  SCIP_VAR* parentvar;
12039 
12040  assert(var != NULL);
12041  assert(*var != NULL);
12042  assert(scalar != NULL);
12043  assert(constant != NULL);
12044 
12045  while( !SCIPvarIsOriginal(*var) )
12046  {
12047  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12048  * var
12049  */
12050  if( (*var)->nparentvars == 0 )
12051  {
12052  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12053  * space
12054  */
12056  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12057  {
12058  *scalar *= -1.0;
12059  *constant -= (*var)->data.negate.constant * (*scalar);
12060  *var = (*var)->negatedvar;
12061 
12062  continue;
12063  }
12064  /* if the variables does not have any parent the variables was created during solving and has no original
12065  * counterpart
12066  */
12067  else
12068  {
12069  *var = NULL;
12070 
12071  return SCIP_OKAY;
12072  }
12073  }
12074 
12075  /* follow the link to the first parent variable */
12076  parentvar = (*var)->parentvars[0];
12077  assert(parentvar != NULL);
12078 
12079  switch( SCIPvarGetStatus(parentvar) )
12080  {
12082  break;
12083 
12084  case SCIP_VARSTATUS_COLUMN:
12085  case SCIP_VARSTATUS_LOOSE:
12086  case SCIP_VARSTATUS_FIXED:
12088  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12089  return SCIP_INVALIDDATA;
12090 
12091  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12092  assert(parentvar->data.aggregate.var == *var);
12093  assert(parentvar->data.aggregate.scalar != 0.0);
12094  *scalar /= parentvar->data.aggregate.scalar;
12095  *constant -= parentvar->data.aggregate.constant * (*scalar);
12096  break;
12097 
12098  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12099  assert(parentvar->negatedvar != NULL);
12100  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12101  assert(parentvar->negatedvar->negatedvar == parentvar);
12102  *scalar *= -1.0;
12103  *constant -= parentvar->data.negate.constant * (*scalar);
12104  break;
12105 
12106  default:
12107  SCIPerrorMessage("unknown variable status\n");
12108  return SCIP_INVALIDDATA;
12109  }
12110 
12111  assert( parentvar != NULL );
12112  *var = parentvar;
12113  }
12114 
12115  return SCIP_OKAY;
12116 }
12117 
12118 /** returns whether the given variable is the direct counterpart of an original problem variable */
12120  SCIP_VAR* var /**< problem variable */
12121  )
12122 {
12123  SCIP_VAR* parentvar;
12124  assert(var != NULL);
12125 
12126  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12127  return FALSE;
12128 
12129  assert(var->parentvars != NULL);
12130  parentvar = var->parentvars[0];
12131  assert(parentvar != NULL);
12132 
12133  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12134  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12135  parentvar = parentvar->parentvars[0];
12136  assert( parentvar != NULL );
12137 
12138  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12139 }
12140 
12141 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12142  * the variable's own data due to diving, that operate only on the LP without updating the variables
12143  */
12145  SCIP_VAR* var /**< problem variable */
12146  )
12147 {
12148  assert(var != NULL);
12149 
12150  /* get bounds of attached variables */
12151  switch( SCIPvarGetStatus(var) )
12152  {
12154  assert(var->data.original.transvar != NULL);
12155  return SCIPvarGetObjLP(var->data.original.transvar);
12156 
12157  case SCIP_VARSTATUS_COLUMN:
12158  assert(var->data.col != NULL);
12159  return SCIPcolGetObj(var->data.col);
12160 
12161  case SCIP_VARSTATUS_LOOSE:
12162  case SCIP_VARSTATUS_FIXED:
12163  return var->obj;
12164 
12165  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12166  assert(var->data.aggregate.var != NULL);
12167  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12168 
12170  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12171  SCIPABORT();
12172  return 0.0; /*lint !e527*/
12173 
12174  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12175  assert(var->negatedvar != NULL);
12177  assert(var->negatedvar->negatedvar == var);
12178  return -SCIPvarGetObjLP(var->negatedvar);
12179 
12180  default:
12181  SCIPerrorMessage("unknown variable status\n");
12182  SCIPABORT();
12183  return 0.0; /*lint !e527*/
12184  }
12185 }
12186 
12187 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12188  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12189  */
12191  SCIP_VAR* var, /**< problem variable */
12192  SCIP_SET* set /**< global SCIP settings */
12193  )
12194 {
12195  assert(var != NULL);
12196  assert(set != NULL);
12197  assert(var->scip == set->scip);
12198 
12199  /* get bounds of attached variables */
12200  switch( SCIPvarGetStatus(var) )
12201  {
12203  assert(var->data.original.transvar != NULL);
12204  return SCIPvarGetLbLP(var->data.original.transvar, set);
12205 
12206  case SCIP_VARSTATUS_COLUMN:
12207  assert(var->data.col != NULL);
12208  return SCIPcolGetLb(var->data.col);
12209 
12210  case SCIP_VARSTATUS_LOOSE:
12211  case SCIP_VARSTATUS_FIXED:
12212  return var->locdom.lb;
12213 
12214  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12215  assert(var->data.aggregate.var != NULL);
12216  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12217  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12218  {
12219  return -SCIPsetInfinity(set);
12220  }
12221  else if( var->data.aggregate.scalar > 0.0 )
12222  {
12223  /* a > 0 -> get lower bound of y */
12224  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12225  }
12226  else if( var->data.aggregate.scalar < 0.0 )
12227  {
12228  /* a < 0 -> get upper bound of y */
12229  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12230  }
12231  else
12232  {
12233  SCIPerrorMessage("scalar is zero in aggregation\n");
12234  SCIPABORT();
12235  return SCIP_INVALID; /*lint !e527*/
12236  }
12237 
12239  /**@todo get the sides of the corresponding linear constraint */
12240  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12241  SCIPABORT();
12242  return SCIP_INVALID; /*lint !e527*/
12243 
12244  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12245  assert(var->negatedvar != NULL);
12247  assert(var->negatedvar->negatedvar == var);
12248  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12249 
12250  default:
12251  SCIPerrorMessage("unknown variable status\n");
12252  SCIPABORT();
12253  return SCIP_INVALID; /*lint !e527*/
12254  }
12255 }
12256 
12257 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12258  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12259  */
12261  SCIP_VAR* var, /**< problem variable */
12262  SCIP_SET* set /**< global SCIP settings */
12263  )
12264 {
12265  assert(var != NULL);
12266  assert(set != NULL);
12267  assert(var->scip == set->scip);
12268 
12269  /* get bounds of attached variables */
12270  switch( SCIPvarGetStatus(var) )
12271  {
12273  assert(var->data.original.transvar != NULL);
12274  return SCIPvarGetUbLP(var->data.original.transvar, set);
12275 
12276  case SCIP_VARSTATUS_COLUMN:
12277  assert(var->data.col != NULL);
12278  return SCIPcolGetUb(var->data.col);
12279 
12280  case SCIP_VARSTATUS_LOOSE:
12281  case SCIP_VARSTATUS_FIXED:
12282  return var->locdom.ub;
12283 
12284  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12285  assert(var->data.aggregate.var != NULL);
12286  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12287  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12288  {
12289  return SCIPsetInfinity(set);
12290  }
12291  if( var->data.aggregate.scalar > 0.0 )
12292  {
12293  /* a > 0 -> get upper bound of y */
12294  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12295  }
12296  else if( var->data.aggregate.scalar < 0.0 )
12297  {
12298  /* a < 0 -> get lower bound of y */
12299  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12300  }
12301  else
12302  {
12303  SCIPerrorMessage("scalar is zero in aggregation\n");
12304  SCIPABORT();
12305  return SCIP_INVALID; /*lint !e527*/
12306  }
12307 
12309  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12310  SCIPABORT();
12311  return SCIP_INVALID; /*lint !e527*/
12312 
12313  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12314  assert(var->negatedvar != NULL);
12316  assert(var->negatedvar->negatedvar == var);
12317  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12318 
12319  default:
12320  SCIPerrorMessage("unknown variable status\n");
12321  SCIPABORT();
12322  return SCIP_INVALID; /*lint !e527*/
12323  }
12324 }
12325 
12326 /** gets primal LP solution value of variable */
12328  SCIP_VAR* var /**< problem variable */
12329  )
12330 {
12331  assert(var != NULL);
12332 
12333  switch( SCIPvarGetStatus(var) )
12334  {
12336  if( var->data.original.transvar == NULL )
12337  return SCIP_INVALID;
12338  return SCIPvarGetLPSol(var->data.original.transvar);
12339 
12340  case SCIP_VARSTATUS_LOOSE:
12341  return SCIPvarGetBestBoundLocal(var);
12342 
12343  case SCIP_VARSTATUS_COLUMN:
12344  assert(var->data.col != NULL);
12345  return SCIPcolGetPrimsol(var->data.col);
12346 
12347  case SCIP_VARSTATUS_FIXED:
12348  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12349  return var->locdom.lb;
12350 
12352  {
12353  SCIP_Real lpsolval;
12354 
12355  assert(var->data.aggregate.var != NULL);
12356  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12357 
12358  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12359  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12360  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12361  * (or is called by) a public interface method; instead, we only assert that values are finite
12362  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12363  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12364  */
12365  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12366  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12367  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12368  }
12370  {
12371  SCIP_Real primsol;
12372  int i;
12373 
12374  assert(!var->donotmultaggr);
12375  assert(var->data.multaggr.vars != NULL);
12376  assert(var->data.multaggr.scalars != NULL);
12377  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12378  * assert(var->data.multaggr.nvars >= 2);
12379  */
12380  primsol = var->data.multaggr.constant;
12381  for( i = 0; i < var->data.multaggr.nvars; ++i )
12382  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12383  return primsol;
12384  }
12385  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12386  assert(var->negatedvar != NULL);
12388  assert(var->negatedvar->negatedvar == var);
12389  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12390 
12391  default:
12392  SCIPerrorMessage("unknown variable status\n");
12393  SCIPABORT();
12394  return SCIP_INVALID; /*lint !e527*/
12395  }
12396 }
12397 
12398 /** gets primal NLP solution value of variable */
12400  SCIP_VAR* var /**< problem variable */
12401  )
12402 {
12403  SCIP_Real solval;
12404  int i;
12405 
12406  assert(var != NULL);
12407 
12408  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12409  switch( SCIPvarGetStatus(var) )
12410  {
12412  return SCIPvarGetNLPSol(var->data.original.transvar);
12413 
12414  case SCIP_VARSTATUS_LOOSE:
12415  case SCIP_VARSTATUS_COLUMN:
12416  return var->nlpsol;
12417 
12418  case SCIP_VARSTATUS_FIXED:
12419  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12420  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12421  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12422  return SCIPvarGetLbGlobal(var);
12423 
12424  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12425  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12426  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12427 
12429  solval = var->data.multaggr.constant;
12430  for( i = 0; i < var->data.multaggr.nvars; ++i )
12431  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12432  return solval;
12433 
12435  solval = SCIPvarGetNLPSol(var->negatedvar);
12436  return var->data.negate.constant - solval;
12437 
12438  default:
12439  SCIPerrorMessage("unknown variable status\n");
12440  SCIPABORT();
12441  return SCIP_INVALID; /*lint !e527*/
12442  }
12443 }
12444 
12445 /** gets pseudo solution value of variable at current node */
12446 static
12448  SCIP_VAR* var /**< problem variable */
12449  )
12450 {
12451  SCIP_Real pseudosol;
12452  int i;
12453 
12454  assert(var != NULL);
12455 
12456  switch( SCIPvarGetStatus(var) )
12457  {
12459  if( var->data.original.transvar == NULL )
12460  return SCIP_INVALID;
12462 
12463  case SCIP_VARSTATUS_LOOSE:
12464  case SCIP_VARSTATUS_COLUMN:
12465  return SCIPvarGetBestBoundLocal(var);
12466 
12467  case SCIP_VARSTATUS_FIXED:
12468  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12469  return var->locdom.lb;
12470 
12472  {
12473  SCIP_Real pseudosolval;
12474  assert(var->data.aggregate.var != NULL);
12475  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12476  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12477  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12478  * (or is called by) a public interface method; instead, we only assert that values are finite
12479  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12480  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12481  */
12482  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12483  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12484  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12485  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12486  }
12488  assert(!var->donotmultaggr);
12489  assert(var->data.multaggr.vars != NULL);
12490  assert(var->data.multaggr.scalars != NULL);
12491  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12492  * assert(var->data.multaggr.nvars >= 2);
12493  */
12494  pseudosol = var->data.multaggr.constant;
12495  for( i = 0; i < var->data.multaggr.nvars; ++i )
12496  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12497  return pseudosol;
12498 
12499  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12500  assert(var->negatedvar != NULL);
12502  assert(var->negatedvar->negatedvar == var);
12503  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12504 
12505  default:
12506  SCIPerrorMessage("unknown variable status\n");
12507  SCIPABORT();
12508  return SCIP_INVALID; /*lint !e527*/
12509  }
12510 }
12511 
12512 /** gets current LP or pseudo solution value of variable */
12514  SCIP_VAR* var, /**< problem variable */
12515  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12516  )
12517 {
12518  if( getlpval )
12519  return SCIPvarGetLPSol(var);
12520  else
12521  return SCIPvarGetPseudoSol(var);
12522 }
12523 
12524 /** remembers the current solution as root solution in the problem variables */
12525 void SCIPvarStoreRootSol(
12526  SCIP_VAR* var, /**< problem variable */
12527  SCIP_Bool roothaslp /**< is the root solution from LP? */
12528  )
12529 {
12530  assert(var != NULL);
12531 
12532  var->rootsol = SCIPvarGetSol(var, roothaslp);
12533 }
12534 
12535 /** updates the current solution as best root solution of the given variable if it is better */
12537  SCIP_VAR* var, /**< problem variable */
12538  SCIP_SET* set, /**< global SCIP settings */
12539  SCIP_Real rootsol, /**< root solution value */
12540  SCIP_Real rootredcost, /**< root reduced cost */
12541  SCIP_Real rootlpobjval /**< objective value of the root LP */
12542  )
12543 {
12544  assert(var != NULL);
12545  assert(set != NULL);
12546  assert(var->scip == set->scip);
12547 
12548  /* if reduced cost are zero nothing to update */
12549  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12550  return;
12551 
12552  /* check if we have already a best combination stored */
12553  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12554  {
12555  SCIP_Real currcutoffbound;
12556  SCIP_Real cutoffbound;
12557  SCIP_Real bound;
12558 
12559  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12560  * root reduced cost, and root LP objective value combination
12561  */
12562  if( var->bestrootredcost > 0.0 )
12563  bound = SCIPvarGetUbGlobal(var);
12564  else
12565  bound = SCIPvarGetLbGlobal(var);
12566 
12567  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12568 
12569  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12570  * cost, and root LP objective value combination
12571  */
12572  if( rootredcost > 0.0 )
12573  bound = SCIPvarGetUbGlobal(var);
12574  else
12575  bound = SCIPvarGetLbGlobal(var);
12576 
12577  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12578 
12579  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12580  if( cutoffbound > currcutoffbound )
12581  {
12582  SCIPdebugMessage("-> <%s> update potetial cutoff bound <%g> -> <%g>\n",
12583  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12584 
12585  var->bestrootsol = rootsol;
12586  var->bestrootredcost = rootredcost;
12587  var->bestrootlpobjval = rootlpobjval;
12588  }
12589  }
12590  else
12591  {
12592  SCIPdebugMessage("-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12593  SCIPdebugMessage(" -> rootsol <%g>\n", rootsol);
12594  SCIPdebugMessage(" -> rootredcost <%g>\n", rootredcost);
12595  SCIPdebugMessage(" -> rootlpobjval <%g>\n", rootlpobjval);
12596 
12597  var->bestrootsol = rootsol;
12598  var->bestrootredcost = rootredcost;
12599  var->bestrootlpobjval = rootlpobjval;
12600  }
12601 }
12602 
12603 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12604  * completely solved, zero is returned
12605  */
12607  SCIP_VAR* var /**< problem variable */
12608  )
12609 {
12610  SCIP_Real rootsol;
12611  int i;
12612 
12613  assert(var != NULL);
12614 
12615  switch( SCIPvarGetStatus(var) )
12616  {
12618  if( var->data.original.transvar == NULL )
12619  return 0.0;
12620  return SCIPvarGetRootSol(var->data.original.transvar);
12621 
12622  case SCIP_VARSTATUS_LOOSE:
12623  case SCIP_VARSTATUS_COLUMN:
12624  return var->rootsol;
12625 
12626  case SCIP_VARSTATUS_FIXED:
12627  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12628  return var->locdom.lb;
12629 
12631  assert(var->data.aggregate.var != NULL);
12632  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12633  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12634  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12635  * (or is called by) a public interface method; instead, we only assert that values are finite
12636  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12637  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12638  */
12642 
12644  assert(!var->donotmultaggr);
12645  assert(var->data.multaggr.vars != NULL);
12646  assert(var->data.multaggr.scalars != NULL);
12647  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12648  * assert(var->data.multaggr.nvars >= 2);
12649  */
12650  rootsol = var->data.multaggr.constant;
12651  for( i = 0; i < var->data.multaggr.nvars; ++i )
12652  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12653  return rootsol;
12654 
12655  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12656  assert(var->negatedvar != NULL);
12658  assert(var->negatedvar->negatedvar == var);
12659  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12660 
12661  default:
12662  SCIPerrorMessage("unknown variable status\n");
12663  SCIPABORT();
12664  return SCIP_INVALID; /*lint !e527*/
12665  }
12666 }
12667 
12668 /** returns for given variable the reduced cost */
12670  SCIP_VAR* var, /**< problem variable */
12671  SCIP_SET* set, /**< global SCIP settings */
12672  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12673  SCIP_STAT* stat, /**< problem statistics */
12674  SCIP_LP* lp /**< current LP data */
12675  )
12676 {
12678  {
12679  SCIP_COL* col;
12680  SCIP_Real primsol;
12681  SCIP_BASESTAT basestat;
12682  SCIP_Bool lpissolbasic;
12683 
12684  col = SCIPvarGetCol(var);
12685  assert(col != NULL);
12686 
12687  basestat = SCIPcolGetBasisStatus(col);
12688  lpissolbasic = SCIPlpIsSolBasic(lp);
12689  primsol = SCIPcolGetPrimsol(col);
12690 
12691  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12692  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12693  {
12694  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12695 
12696  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12697  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12699  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12700  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12701  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12702 
12703  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12704  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12705  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12706  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12707  return redcost;
12708  else
12709  return 0.0;
12710  }
12711 
12712  return 0.0;
12713  }
12714 
12715  return 0.0;
12716 }
12717 
12718 #define MAX_CLIQUELENGTH 50
12719 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12720  * the binary variable is fixed to the given value
12721  */
12723  SCIP_VAR* var, /**< problem variable */
12724  SCIP_SET* set, /**< global SCIP settings */
12725  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12726  SCIP_STAT* stat, /**< problem statistics */
12727  SCIP_PROB* prob, /**< transformed problem, or NULL */
12728  SCIP_LP* lp /**< current LP data */
12729  )
12730 {
12731  SCIP_Real implredcost;
12732  int ncliques;
12733  int nvars;
12734 
12735  assert(SCIPvarIsBinary(var));
12736  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12737 
12738  /* get reduced cost of given variable */
12739  implredcost = SCIPvarGetRedcost(var, set, varfixing, stat, lp);
12740 
12741 #ifdef SCIP_MORE_DEBUG
12742  SCIPdebugMessage("variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12743 #endif
12744 
12745  /* the following algorithm is expensive */
12746  ncliques = SCIPvarGetNCliques(var, varfixing);
12747 
12748  if( ncliques > 0 )
12749  {
12750  SCIP_CLIQUE** cliques;
12751  SCIP_CLIQUE* clique;
12752  SCIP_VAR** clqvars;
12753  SCIP_VAR** probvars;
12754  SCIP_VAR* clqvar;
12755  SCIP_Bool* clqvalues;
12756  int* entries;
12757  int* ids;
12758  SCIP_Real redcost;
12759  SCIP_Bool cleanedup;
12760  int nclqvars;
12761  int nentries;
12762  int nids;
12763  int id;
12764  int c;
12765  int v;
12766 
12767  assert(prob != NULL);
12768  assert(SCIPprobIsTransformed(prob));
12769 
12770  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12771 
12772  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
12773  nids = 0;
12774  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
12775 
12776  cliques = SCIPvarGetCliques(var, varfixing);
12777  assert(cliques != NULL);
12778 
12779  for( c = ncliques - 1; c >= 0; --c )
12780  {
12781  clique = cliques[c];
12782  assert(clique != NULL);
12783  nclqvars = SCIPcliqueGetNVars(clique);
12784  assert(nclqvars > 0);
12785 
12786  if( nclqvars > MAX_CLIQUELENGTH )
12787  continue;
12788 
12789  clqvars = SCIPcliqueGetVars(clique);
12790  clqvalues = SCIPcliqueGetValues(clique);
12791  assert(clqvars != NULL);
12792  assert(clqvalues != NULL);
12793 
12794  cleanedup = SCIPcliqueIsCleanedUp(clique);
12795 
12796  for( v = nclqvars - 1; v >= 0; --v )
12797  {
12798  clqvar = clqvars[v];
12799  assert(clqvar != NULL);
12800 
12801  /* ignore binary variable which are fixed */
12802  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
12803  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
12804  {
12805  int probindex = SCIPvarGetProbindex(clqvar) + 1;
12806  assert(0 < probindex && probindex < nentries);
12807 
12808 #if 0
12809  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
12810  * can appear since there is no guarantee that all these infeasible bounds were found
12811  */
12812  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
12813 #endif
12814  if( entries[probindex] == 0 )
12815  {
12816  ids[nids] = probindex;
12817  ++nids;
12818 
12819  /* mark variable as visited */
12820  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
12821  }
12822  }
12823  }
12824  }
12825 
12826  probvars = SCIPprobGetVars(prob);
12827  assert(probvars != NULL);
12828 
12829  /* add all implied reduced cost */
12830  for( v = nids - 1; v >= 0; --v )
12831  {
12832  id = ids[v];
12833  assert(0 < id && id < nentries);
12834  assert(entries[id] != 0);
12835  assert(probvars[id - 1] != NULL);
12836  assert(SCIPvarIsActive(probvars[id - 1]));
12837  assert(SCIPvarIsBinary(probvars[id - 1]));
12838  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
12839 
12840  if( (entries[id] > 0) != varfixing )
12841  redcost = SCIPvarGetRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12842  else
12843  redcost = -SCIPvarGetRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12844 
12845  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
12846  implredcost += redcost;
12847 
12848  /* reset entries clear buffer array */
12849  entries[id] = 0;
12850  }
12851 
12852  SCIPsetFreeCleanBufferArray(set, &entries);
12853  SCIPsetFreeBufferArray(set, &ids);
12854  }
12855 
12856 #ifdef SCIP_MORE_DEBUG
12857  SCIPdebugMessage("variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
12858  implredcost);
12859 #endif
12860 
12861  /* collect non-binary implication information */
12862  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
12863 
12864  if( nvars > 0 )
12865  {
12866  SCIP_VAR** vars;
12867  SCIP_VAR* implvar;
12868  SCIP_COL* col;
12869  SCIP_Real* bounds;
12870  SCIP_BOUNDTYPE* boundtypes;
12871  SCIP_Real redcost;
12872  SCIP_Real lb;
12873  SCIP_Real ub;
12874  SCIP_Bool lpissolbasic;
12875  int v;
12876 
12877  vars = SCIPimplicsGetVars(var->implics, varfixing);
12878  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
12879  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
12880  lpissolbasic = SCIPlpIsSolBasic(lp);
12881 
12882  for( v = nvars - 1; v >= 0; --v )
12883  {
12884  implvar = vars[v];
12885  assert(implvar != NULL);
12886 
12887  lb = SCIPvarGetLbLocal(implvar);
12888  ub = SCIPvarGetUbLocal(implvar);
12889 
12890  /* ignore binary variable which are fixed or not of column status */
12891  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
12892  continue;
12893 
12894  col = SCIPvarGetCol(implvar);
12895  assert(col != NULL);
12896  redcost = 0.0;
12897 
12898  /* solved lp with basis information or not? */
12899  if( lpissolbasic )
12900  {
12901  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
12902 
12903  /* check if the implication is not not yet applied */
12904  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
12905  {
12906  redcost = SCIPcolGetRedcost(col, stat, lp);
12907  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12908 
12909  if( !varfixing )
12910  redcost *= (lb - bounds[v]);
12911  else
12912  redcost *= (bounds[v] - lb);
12913  }
12914  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
12915  {
12916  redcost = SCIPcolGetRedcost(col, stat, lp);
12917  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12918 
12919  if( varfixing )
12920  redcost *= (bounds[v] - ub);
12921  else
12922  redcost *= (ub - bounds[v]);
12923  }
12924  }
12925  else
12926  {
12927  SCIP_Real primsol = SCIPcolGetPrimsol(col);
12928 
12929  /* check if the implication is not not yet applied */
12930  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
12931  {
12932  redcost = SCIPcolGetRedcost(col, stat, lp);
12933  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12934 
12935  if( varfixing )
12936  redcost *= (lb - bounds[v]);
12937  else
12938  redcost *= (bounds[v] - lb);
12939  }
12940  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
12941  {
12942  redcost = SCIPcolGetRedcost(col, stat, lp);
12943  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12944 
12945  if( varfixing )
12946  redcost *= (bounds[v] - ub);
12947  else
12948  redcost *= (ub - bounds[v]);
12949  }
12950  }
12951 
12952  /* improve implied reduced cost */
12953  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
12954  implredcost += redcost;
12955  }
12956  }
12957 
12958 #ifdef SCIP_MORE_DEBUG
12959  SCIPdebugMessage("variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
12960  SCIPvarGetName(var), ncliques, nvars, implredcost);
12961 #endif
12962 
12963  return implredcost;
12964 }
12965 
12966 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
12967  * the root relaxation is not yet completely solved, zero is returned
12968  */
12970  SCIP_VAR* var /**< problem variable */
12971  )
12972 {
12973  SCIP_Real rootsol;
12974  int i;
12975 
12976  assert(var != NULL);
12977 
12978  switch( SCIPvarGetStatus(var) )
12979  {
12981  if( var->data.original.transvar == NULL )
12982  return 0.0;
12984 
12985  case SCIP_VARSTATUS_LOOSE:
12986  case SCIP_VARSTATUS_COLUMN:
12987  return var->bestrootsol;
12988 
12989  case SCIP_VARSTATUS_FIXED:
12990  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12991  return var->locdom.lb;
12992 
12994  assert(var->data.aggregate.var != NULL);
12995  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12996  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12997  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12998  * (or is called by) a public interface method; instead, we only assert that values are finite
12999  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13000  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13001  */
13005 
13007  assert(!var->donotmultaggr);
13008  assert(var->data.multaggr.vars != NULL);
13009  assert(var->data.multaggr.scalars != NULL);
13010  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13011  * assert(var->data.multaggr.nvars >= 2);
13012  */
13013  rootsol = var->data.multaggr.constant;
13014  for( i = 0; i < var->data.multaggr.nvars; ++i )
13015  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13016  return rootsol;
13017 
13018  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13019  assert(var->negatedvar != NULL);
13021  assert(var->negatedvar->negatedvar == var);
13022  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13023 
13024  default:
13025  SCIPerrorMessage("unknown variable status\n");
13026  SCIPABORT();
13027  return 0.0; /*lint !e527*/
13028  }
13029 }
13030 
13031 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13032  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13033  * returned
13034  */
13036  SCIP_VAR* var /**< problem variable */
13037  )
13038 {
13039  assert(var != NULL);
13040 
13041  switch( SCIPvarGetStatus(var) )
13042  {
13044  if( var->data.original.transvar == NULL )
13045  return SCIP_INVALID;
13047 
13048  case SCIP_VARSTATUS_LOOSE:
13049  case SCIP_VARSTATUS_COLUMN:
13050  return var->bestrootredcost;
13051 
13052  case SCIP_VARSTATUS_FIXED:
13056  return 0.0;
13057 
13058  default:
13059  SCIPerrorMessage("unknown variable status\n");
13060  SCIPABORT();
13061  return 0.0; /*lint !e527*/
13062  }
13063 }
13064 
13065 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13066  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13067  * SCIP_INVALID is returned
13068  */
13070  SCIP_VAR* var /**< problem variable */
13071  )
13072 {
13073  assert(var != NULL);
13074 
13075  switch( SCIPvarGetStatus(var) )
13076  {
13078  if( var->data.original.transvar == NULL )
13079  return SCIP_INVALID;
13081 
13082  case SCIP_VARSTATUS_LOOSE:
13083  case SCIP_VARSTATUS_COLUMN:
13084  return var->bestrootlpobjval;
13085 
13086  case SCIP_VARSTATUS_FIXED:
13090  return SCIP_INVALID;
13091 
13092  default:
13093  SCIPerrorMessage("unknown variable status\n");
13094  SCIPABORT();
13095  return SCIP_INVALID; /*lint !e527*/
13096  }
13097 }
13098 
13099 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13101  SCIP_VAR* var, /**< problem variable */
13102  SCIP_Real rootsol, /**< root solution value */
13103  SCIP_Real rootredcost, /**< root reduced cost */
13104  SCIP_Real rootlpobjval /**< objective value of the root LP */
13105  )
13106 {
13107  assert(var != NULL);
13108 
13109  var->bestrootsol = rootsol;
13110  var->bestrootredcost = rootredcost;
13111  var->bestrootlpobjval = rootlpobjval;
13112 }
13113 
13114 /** stores the solution value as relaxation solution in the problem variable */
13116  SCIP_VAR* var, /**< problem variable */
13117  SCIP_SET* set, /**< global SCIP settings */
13118  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13119  SCIP_Real solval, /**< solution value in the current relaxation solution */
13120  SCIP_Bool updateobj /**< should the objective value be updated? */
13121  )
13122 {
13123  assert(var != NULL);
13124  assert(relaxation != NULL);
13125  assert(set != NULL);
13126  assert(var->scip == set->scip);
13127 
13128  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13129  switch( SCIPvarGetStatus(var) )
13130  {
13132  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13133  break;
13134 
13135  case SCIP_VARSTATUS_LOOSE:
13136  case SCIP_VARSTATUS_COLUMN:
13137  if( updateobj )
13138  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13139  var->relaxsol = solval;
13140  break;
13141 
13142  case SCIP_VARSTATUS_FIXED:
13143  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13144  {
13145  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13146  SCIPvarGetName(var), var->glbdom.lb, solval);
13147  return SCIP_INVALIDDATA;
13148  }
13149  break;
13150 
13151  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13152  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13153  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13154  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13155  break;
13157  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13158  return SCIP_INVALIDDATA;
13159 
13161  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13162  break;
13163 
13164  default:
13165  SCIPerrorMessage("unknown variable status\n");
13166  return SCIP_INVALIDDATA;
13167  }
13168 
13169  return SCIP_OKAY;
13170 }
13171 
13172 /** returns the solution value of the problem variable in the relaxation solution
13173  *
13174  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13175  */
13177  SCIP_VAR* var, /**< problem variable */
13178  SCIP_SET* set /**< global SCIP settings */
13179  )
13180 {
13181  SCIP_Real solvalsum;
13182  SCIP_Real solval;
13183  int i;
13184 
13185  assert(var != NULL);
13186  assert(set != NULL);
13187  assert(var->scip == set->scip);
13188 
13189  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13190  switch( SCIPvarGetStatus(var) )
13191  {
13193  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13194 
13195  case SCIP_VARSTATUS_LOOSE:
13196  case SCIP_VARSTATUS_COLUMN:
13197  return var->relaxsol;
13198 
13199  case SCIP_VARSTATUS_FIXED:
13200  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13201  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13202  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13203  return SCIPvarGetLbGlobal(var);
13204 
13205  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13206  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13207  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13208  {
13209  if( var->data.aggregate.scalar * solval > 0.0 )
13210  return SCIPsetInfinity(set);
13211  if( var->data.aggregate.scalar * solval < 0.0 )
13212  return -SCIPsetInfinity(set);
13213  }
13214  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13215 
13217  solvalsum = var->data.multaggr.constant;
13218  for( i = 0; i < var->data.multaggr.nvars; ++i )
13219  {
13220  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13221  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13222  {
13223  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13224  return SCIPsetInfinity(set);
13225  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13226  return -SCIPsetInfinity(set);
13227  }
13228  solvalsum += var->data.multaggr.scalars[i] * solval;
13229  }
13230  return solvalsum;
13231 
13233  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13234  if( SCIPsetIsInfinity(set, solval) )
13235  return -SCIPsetInfinity(set);
13236  if( SCIPsetIsInfinity(set, -solval) )
13237  return SCIPsetInfinity(set);
13238  return var->data.negate.constant - solval;
13239 
13240  default:
13241  SCIPerrorMessage("unknown variable status\n");
13242  SCIPABORT();
13243  return SCIP_INVALID; /*lint !e527*/
13244  }
13245 }
13246 
13247 /** returns the solution value of the transformed problem variable in the relaxation solution */
13249  SCIP_VAR* var /**< problem variable */
13250  )
13251 {
13252  assert(var != NULL);
13254 
13255  return var->relaxsol;
13256 }
13257 
13258 /** stores the solution value as NLP solution in the problem variable */
13260  SCIP_VAR* var, /**< problem variable */
13261  SCIP_SET* set, /**< global SCIP settings */
13262  SCIP_Real solval /**< solution value in the current NLP solution */
13263  )
13264 {
13265  assert(var != NULL);
13266  assert(set != NULL);
13267  assert(var->scip == set->scip);
13268 
13269  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13270  switch( SCIPvarGetStatus(var) )
13271  {
13273  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13274  break;
13275 
13276  case SCIP_VARSTATUS_LOOSE:
13277  case SCIP_VARSTATUS_COLUMN:
13278  var->nlpsol = solval;
13279  break;
13280 
13281  case SCIP_VARSTATUS_FIXED:
13282  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13283  {
13284  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13285  SCIPvarGetName(var), var->glbdom.lb, solval);
13286  SCIPABORT();
13287  return SCIP_INVALIDCALL; /*lint !e527*/
13288  }
13289  break;
13290 
13291  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13292  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13293  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13294  break;
13295 
13297  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13298  SCIPABORT();
13299  return SCIP_INVALIDCALL; /*lint !e527*/
13300 
13302  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13303  break;
13304 
13305  default:
13306  SCIPerrorMessage("unknown variable status\n");
13307  SCIPABORT();
13308  return SCIP_ERROR; /*lint !e527*/
13309  }
13310 
13311  return SCIP_OKAY;
13312 }
13313 
13314 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13316  SCIP_VAR* var /**< problem variable */
13317  )
13318 {
13319  SCIP_Real avgsol;
13320  int i;
13321 
13322  assert(var != NULL);
13323 
13324  switch( SCIPvarGetStatus(var) )
13325  {
13327  if( var->data.original.transvar == NULL )
13328  return 0.0;
13329  return SCIPvarGetAvgSol(var->data.original.transvar);
13330 
13331  case SCIP_VARSTATUS_LOOSE:
13332  case SCIP_VARSTATUS_COLUMN:
13333  avgsol = var->primsolavg;
13334  avgsol = MAX(avgsol, var->glbdom.lb);
13335  avgsol = MIN(avgsol, var->glbdom.ub);
13336  return avgsol;
13337 
13338  case SCIP_VARSTATUS_FIXED:
13339  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13340  return var->locdom.lb;
13341 
13343  assert(var->data.aggregate.var != NULL);
13344  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13345  + var->data.aggregate.constant;
13346 
13348  assert(!var->donotmultaggr);
13349  assert(var->data.multaggr.vars != NULL);
13350  assert(var->data.multaggr.scalars != NULL);
13351  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13352  * assert(var->data.multaggr.nvars >= 2);
13353  */
13354  avgsol = var->data.multaggr.constant;
13355  for( i = 0; i < var->data.multaggr.nvars; ++i )
13356  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13357  return avgsol;
13358 
13359  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13360  assert(var->negatedvar != NULL);
13362  assert(var->negatedvar->negatedvar == var);
13363  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13364 
13365  default:
13366  SCIPerrorMessage("unknown variable status\n");
13367  SCIPABORT();
13368  return 0.0; /*lint !e527*/
13369  }
13370 }
13371 
13372 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13373  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13374  */
13376  SCIP_VAR* var, /**< active problem variable */
13377  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13378  SCIP_SET* set, /**< global SCIP settings */
13379  SCIP_STAT* stat, /**< problem statistics */
13380  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13381  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13382  )
13383 {
13384  int nvlbs;
13385 
13386  assert(var != NULL);
13387  assert(stat != NULL);
13388  assert(set != NULL);
13389  assert(var->scip == set->scip);
13390  assert(closestvlb != NULL);
13391  assert(closestvlbidx != NULL);
13392 
13393  *closestvlbidx = -1;
13394  *closestvlb = SCIP_REAL_MIN;
13395 
13396  nvlbs = SCIPvarGetNVlbs(var);
13397  if( nvlbs > 0 )
13398  {
13399  SCIP_VAR** vlbvars;
13400  SCIP_Real* vlbcoefs;
13401  SCIP_Real* vlbconsts;
13402  int i;
13403 
13404  vlbvars = SCIPvarGetVlbVars(var);
13405  vlbcoefs = SCIPvarGetVlbCoefs(var);
13406  vlbconsts = SCIPvarGetVlbConstants(var);
13407 
13408  /* check for cached values */
13409  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13410  {
13411  i = var->closestvlbidx;
13412  assert(0 <= i && i < nvlbs);
13413  assert(SCIPvarIsActive(vlbvars[i]));
13414  *closestvlbidx = i;
13415  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13416  }
13417  else
13418  {
13419  /* search best VUB */
13420  for( i = 0; i < nvlbs; i++ )
13421  {
13422  if( SCIPvarIsActive(vlbvars[i]) )
13423  {
13424  SCIP_Real vlbsol;
13425 
13426  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13427  if( vlbsol > *closestvlb )
13428  {
13429  *closestvlb = vlbsol;
13430  *closestvlbidx = i;
13431  }
13432  }
13433  }
13434 
13435  if( sol == NULL )
13436  {
13437  /* update cached value */
13438  if( var->closestvblpcount != stat->lpcount )
13439  var->closestvubidx = -1;
13440  var->closestvlbidx = *closestvlbidx;
13441  var->closestvblpcount = stat->lpcount;
13442  }
13443  }
13444  }
13445 }
13446 
13447 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13448  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13449  */
13451  SCIP_VAR* var, /**< active problem variable */
13452  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13453  SCIP_SET* set, /**< global SCIP settings */
13454  SCIP_STAT* stat, /**< problem statistics */
13455  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13456  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13457  )
13458 {
13459  int nvubs;
13460 
13461  assert(var != NULL);
13462  assert(set != NULL);
13463  assert(var->scip == set->scip);
13464  assert(closestvub != NULL);
13465  assert(closestvubidx != NULL);
13466 
13467  *closestvubidx = -1;
13468  *closestvub = SCIP_REAL_MAX;
13469 
13470  nvubs = SCIPvarGetNVubs(var);
13471  if( nvubs > 0 )
13472  {
13473  SCIP_VAR** vubvars;
13474  SCIP_Real* vubcoefs;
13475  SCIP_Real* vubconsts;
13476  int i;
13477 
13478  vubvars = SCIPvarGetVubVars(var);
13479  vubcoefs = SCIPvarGetVubCoefs(var);
13480  vubconsts = SCIPvarGetVubConstants(var);
13481 
13482  /* check for cached values */
13483  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13484  {
13485  i = var->closestvubidx;
13486  assert(0 <= i && i < nvubs);
13487  assert(SCIPvarIsActive(vubvars[i]));
13488  *closestvubidx = i;
13489  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13490  }
13491  else
13492  {
13493  /* search best VUB */
13494  for( i = 0; i < nvubs; i++ )
13495  {
13496  if( SCIPvarIsActive(vubvars[i]) )
13497  {
13498  SCIP_Real vubsol;
13499 
13500  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13501  if( vubsol < *closestvub )
13502  {
13503  *closestvub = vubsol;
13504  *closestvubidx = i;
13505  }
13506  }
13507  }
13508 
13509  if( sol == NULL )
13510  {
13511  /* update cached value */
13512  if( var->closestvblpcount != stat->lpcount )
13513  var->closestvlbidx = -1;
13514  var->closestvubidx = *closestvubidx;
13515  var->closestvblpcount = stat->lpcount;
13516  }
13517  }
13518  }
13519 }
13520 
13521 /** resolves variable to columns and adds them with the coefficient to the row */
13523  SCIP_VAR* var, /**< problem variable */
13524  BMS_BLKMEM* blkmem, /**< block memory */
13525  SCIP_SET* set, /**< global SCIP settings */
13526  SCIP_STAT* stat, /**< problem statistics */
13527  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13528  SCIP_PROB* prob, /**< problem data */
13529  SCIP_LP* lp, /**< current LP data */
13530  SCIP_ROW* row, /**< LP row */
13531  SCIP_Real val /**< value of coefficient */
13532  )
13533 {
13534  int i;
13535 
13536  assert(var != NULL);
13537  assert(set != NULL);
13538  assert(var->scip == set->scip);
13539  assert(row != NULL);
13540  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13541 
13542  SCIPdebugMessage("adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13543 
13544  if ( SCIPsetIsZero(set, val) )
13545  return SCIP_OKAY;
13546 
13547  switch( SCIPvarGetStatus(var) )
13548  {
13550  if( var->data.original.transvar == NULL )
13551  {
13552  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13553  return SCIP_INVALIDDATA;
13554  }
13555  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13556  return SCIP_OKAY;
13557 
13558  case SCIP_VARSTATUS_LOOSE:
13559  /* add globally fixed variables as constant */
13560  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13561  {
13562  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13563  return SCIP_OKAY;
13564  }
13565  /* convert loose variable into column */
13566  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13567  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13568  /*lint -fallthrough*/
13569 
13570  case SCIP_VARSTATUS_COLUMN:
13571  assert(var->data.col != NULL);
13572  assert(var->data.col->var == var);
13573  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13574  return SCIP_OKAY;
13575 
13576  case SCIP_VARSTATUS_FIXED:
13577  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13578  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13579  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13580  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13581  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13582  return SCIP_OKAY;
13583 
13585  assert(var->data.aggregate.var != NULL);
13586  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13587  row, var->data.aggregate.scalar * val) );
13588  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13589  return SCIP_OKAY;
13590 
13592  assert(!var->donotmultaggr);
13593  assert(var->data.multaggr.vars != NULL);
13594  assert(var->data.multaggr.scalars != NULL);
13595  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13596  * assert(var->data.multaggr.nvars >= 2);
13597  */
13598  for( i = 0; i < var->data.multaggr.nvars; ++i )
13599  {
13600  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13601  row, var->data.multaggr.scalars[i] * val) );
13602  }
13603  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13604  return SCIP_OKAY;
13605 
13606  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13607  assert(var->negatedvar != NULL);
13609  assert(var->negatedvar->negatedvar == var);
13610  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13611  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13612  return SCIP_OKAY;
13613 
13614  default:
13615  SCIPerrorMessage("unknown variable status\n");
13616  return SCIP_INVALIDDATA;
13617  }
13618 }
13619 
13620 /* optionally, define this compiler flag to write complete variable histories to a file */
13621 #ifdef SCIP_HISTORYTOFILE
13622 SCIP_Longint counter = 0l;
13623 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13624 #endif
13625 
13626 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13627  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13628  */
13630  SCIP_VAR* var, /**< problem variable */
13631  SCIP_SET* set, /**< global SCIP settings */
13632  SCIP_STAT* stat, /**< problem statistics */
13633  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13634  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13635  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13636  )
13637 {
13638  assert(var != NULL);
13639  assert(set != NULL);
13640  assert(var->scip == set->scip);
13641  assert(stat != NULL);
13642 
13643  /* check if history statistics should be collected for a variable */
13644  if( !stat->collectvarhistory )
13645  return SCIP_OKAY;
13646 
13647  switch( SCIPvarGetStatus(var) )
13648  {
13650  if( var->data.original.transvar == NULL )
13651  {
13652  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13653  return SCIP_INVALIDDATA;
13654  }
13655  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13656  return SCIP_OKAY;
13657 
13658  case SCIP_VARSTATUS_LOOSE:
13659  case SCIP_VARSTATUS_COLUMN:
13660  /* append history to file */
13661 #ifdef SCIP_HISTORYTOFILE
13662  {
13663  FILE* f;
13664  char filename[256];
13665 
13666  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13667  f = fopen(filename, "a");
13668  if( NULL != f )
13669  {
13670  fprintf(f, "%lld %s \t %lld \t %d %15.9f %.3f\n", ++counter,
13671  SCIPvarGetName(var), stat->nnodes, SCIPgetDepth(set->scip), objdelta, solvaldelta);
13672  fclose(f);
13673  }
13674  }
13675 #endif
13676  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13677  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13678  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13679  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13680  return SCIP_OKAY;
13681 
13682  case SCIP_VARSTATUS_FIXED:
13683  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13684  return SCIP_INVALIDDATA;
13685 
13687  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13689  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13690  return SCIP_OKAY;
13691 
13693  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13694  return SCIP_INVALIDDATA;
13695 
13697  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13698  return SCIP_OKAY;
13699 
13700  default:
13701  SCIPerrorMessage("unknown variable status\n");
13702  return SCIP_INVALIDDATA;
13703  }
13704 }
13705 
13706 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13708  SCIP_VAR* var, /**< problem variable */
13709  SCIP_STAT* stat, /**< problem statistics */
13710  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13711  )
13712 {
13713  SCIP_BRANCHDIR dir;
13714 
13715  assert(var != NULL);
13716  assert(stat != NULL);
13717 
13718  switch( SCIPvarGetStatus(var) )
13719  {
13721  if( var->data.original.transvar == NULL )
13722  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13723  else
13724  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13725 
13726  case SCIP_VARSTATUS_LOOSE:
13727  case SCIP_VARSTATUS_COLUMN:
13728  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13729 
13730  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13731  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13732  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13733 
13734  case SCIP_VARSTATUS_FIXED:
13735  return 0.0;
13736 
13738  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13739 
13741  return 0.0;
13742 
13744  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13745 
13746  default:
13747  SCIPerrorMessage("unknown variable status\n");
13748  SCIPABORT();
13749  return 0.0; /*lint !e527*/
13750  }
13751 }
13752 
13753 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13754  * only using the pseudo cost information of the current run
13755  */
13757  SCIP_VAR* var, /**< problem variable */
13758  SCIP_STAT* stat, /**< problem statistics */
13759  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13760  )
13761 {
13762  SCIP_BRANCHDIR dir;
13763 
13764  assert(var != NULL);
13765  assert(stat != NULL);
13766 
13767  switch( SCIPvarGetStatus(var) )
13768  {
13770  if( var->data.original.transvar == NULL )
13771  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13772  else
13773  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
13774 
13775  case SCIP_VARSTATUS_LOOSE:
13776  case SCIP_VARSTATUS_COLUMN:
13777  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13778 
13779  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
13780  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
13781  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13782 
13783  case SCIP_VARSTATUS_FIXED:
13784  return 0.0;
13785 
13787  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13788 
13790  return 0.0;
13791 
13793  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
13794 
13795  default:
13796  SCIPerrorMessage("unknown variable status\n");
13797  SCIPABORT();
13798  return 0.0; /*lint !e527*/
13799  }
13800 }
13801 
13802 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
13804  SCIP_VAR* var, /**< problem variable */
13805  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13806  )
13807 {
13808  assert(var != NULL);
13809  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13810 
13811  switch( SCIPvarGetStatus(var) )
13812  {
13814  if( var->data.original.transvar == NULL )
13815  return 0.0;
13816  else
13817  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
13818 
13819  case SCIP_VARSTATUS_LOOSE:
13820  case SCIP_VARSTATUS_COLUMN:
13821  return SCIPhistoryGetPseudocostCount(var->history, dir);
13822 
13823  case SCIP_VARSTATUS_FIXED:
13824  return 0.0;
13825 
13827  if( var->data.aggregate.scalar > 0.0 )
13828  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
13829  else
13831 
13833  return 0.0;
13834 
13837 
13838  default:
13839  SCIPerrorMessage("unknown variable status\n");
13840  SCIPABORT();
13841  return 0.0; /*lint !e527*/
13842  }
13843 }
13844 
13845 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
13846  * only using the pseudo cost information of the current run
13847  */
13849  SCIP_VAR* var, /**< problem variable */
13850  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13851  )
13852 {
13853  assert(var != NULL);
13854  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13855 
13856  switch( SCIPvarGetStatus(var) )
13857  {
13859  if( var->data.original.transvar == NULL )
13860  return 0.0;
13861  else
13863 
13864  case SCIP_VARSTATUS_LOOSE:
13865  case SCIP_VARSTATUS_COLUMN:
13866  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
13867 
13868  case SCIP_VARSTATUS_FIXED:
13869  return 0.0;
13870 
13872  if( var->data.aggregate.scalar > 0.0 )
13874  else
13876 
13878  return 0.0;
13879 
13882 
13883  default:
13884  SCIPerrorMessage("unknown variable status\n");
13885  SCIPABORT();
13886  return 0.0; /*lint !e527*/
13887  }
13888 }
13889 
13890 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
13892  SCIP_VAR* var, /**< problem variable */
13893  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
13894  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
13895  )
13896 {
13897  assert(var != NULL);
13898  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13899 
13900  switch( SCIPvarGetStatus(var) )
13901  {
13903  if( var->data.original.transvar == NULL )
13904  return 0.0;
13905  else
13906  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
13907 
13908  case SCIP_VARSTATUS_LOOSE:
13909  case SCIP_VARSTATUS_COLUMN:
13910  if( onlycurrentrun )
13912  else
13913  return SCIPhistoryGetPseudocostVariance(var->history, dir);
13914 
13915  case SCIP_VARSTATUS_FIXED:
13916  return 0.0;
13917 
13919  if( var->data.aggregate.scalar > 0.0 )
13920  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
13921  else
13922  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
13923 
13925  return 0.0;
13926 
13928  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
13929 
13930  default:
13931  SCIPerrorMessage("unknown variable status\n");
13932  SCIPABORT();
13933  return 0.0; /*lint !e527*/
13934  }
13935 }
13936 
13937 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
13938  *
13939  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
13940  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
13941  * of 2 * clevel - 1.
13942  *
13943  * @return value of confidence bound for this variable
13944  */
13946  SCIP_VAR* var, /**< variable in question */
13947  SCIP_SET* set, /**< global SCIP settings */
13948  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
13949  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
13950  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
13951  )
13952 {
13953  SCIP_Real confidencebound;
13954 
13955  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
13956  if( SCIPsetIsFeasPositive(set, confidencebound) )
13957  {
13958  SCIP_Real count;
13959 
13960  if( onlycurrentrun )
13961  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
13962  else
13963  count = SCIPvarGetPseudocostCount(var, dir);
13964  /* assertion is valid because variance is positive */
13965  assert(count >= 1.9);
13966 
13967  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
13968  confidencebound = sqrt(confidencebound);
13969 
13970  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
13971  * the number of pseudo cost evaluations of this variable in the respective direction. */
13972  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
13973  }
13974  else
13975  confidencebound = 0.0;
13976 
13977  return confidencebound;
13978 }
13979 
13980 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
13981  * Error is calculated at a specific confidence level
13982  */
13984  SCIP_VAR* var, /**< variable in question */
13985  SCIP_SET* set, /**< global SCIP settings */
13986  SCIP_STAT* stat, /**< problem statistics */
13987  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
13988  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
13989  )
13990 {
13991  SCIP_Real downsize;
13992  SCIP_Real upsize;
13993  SCIP_Real size;
13994  SCIP_Real relerrorup;
13995  SCIP_Real relerrordown;
13996  SCIP_Real relerror;
13997 
13998  /* check, if the pseudo cost score of the variable is reliable */
14001  size = MIN(downsize, upsize);
14002 
14003  relerrordown = 0.0;
14004  relerrorup = 0.0;
14005 
14006  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14007  if( size <= 1.9 )
14008  return FALSE;
14009 
14010  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14011  * confidence interval bound at confidence level of 95% for individual variable reliability.
14012  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14013  */
14014  if( downsize >= 1.9 )
14015  {
14016  SCIP_Real normval;
14017 
14018  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14019  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14020  normval = MAX(1.0, normval);
14021 
14022  relerrordown /= normval;
14023  }
14024  else
14025  relerrordown = 0.0;
14026 
14027  if( upsize >= 1.9 )
14028  {
14029  SCIP_Real normval;
14030 
14031  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14032  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14033  normval = MAX(1.0, normval);
14034  relerrorup /= normval;
14035  }
14036  else
14037  relerrorup = 0.0;
14038 
14039  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14040  relerror = MAX(relerrorup, relerrordown);
14041 
14042  return (relerror <= threshold);
14043 }
14044 
14045 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14046  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14047  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14048  * unknown location means of the underlying pseudo-cost distributions of x and y.
14049  *
14050  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14051  * better than x (despite the current information), meaning that y can be expected to yield branching
14052  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14053  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14054  * than y.
14055  *
14056  * @note The order of x and y matters for the one-sided hypothesis
14057  *
14058  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14059  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14060  *
14061  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14062  */
14064  SCIP_SET* set, /**< global SCIP settings */
14065  SCIP_STAT* stat, /**< problem statistics */
14066  SCIP_VAR* varx, /**< variable x */
14067  SCIP_Real fracx, /**< the fractionality of variable x */
14068  SCIP_VAR* vary, /**< variable y */
14069  SCIP_Real fracy, /**< the fractionality of variable y */
14070  SCIP_BRANCHDIR dir, /**< branching direction */
14071  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14072  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14073  )
14074 {
14075  SCIP_Real meanx;
14076  SCIP_Real meany;
14077  SCIP_Real variancex;
14078  SCIP_Real variancey;
14079  SCIP_Real countx;
14080  SCIP_Real county;
14081  SCIP_Real tresult;
14082  SCIP_Real realdirection;
14083 
14084 
14085  if( varx == vary )
14086  return FALSE;
14087 
14088  countx = SCIPvarGetPseudocostCount(varx, dir);
14089  county = SCIPvarGetPseudocostCount(vary, dir);
14090 
14091  /* if not at least 2 measurements were taken, return FALSE */
14092  if( countx <= 1.9 || county <= 1.9 )
14093  return FALSE;
14094 
14095  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14096 
14097  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14098  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14099 
14100  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14101  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14102 
14103  /* if there is no variance, the means are taken from a constant distribution */
14104  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14105  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14106 
14107  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14108 
14109  /* for the two-sided hypothesis, just take the absolute of t */
14110  if( !onesided )
14111  tresult = REALABS(tresult);
14112 
14113  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14114 }
14115 
14116 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14117  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14118  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14119  * of at least \p threshold.
14120  *
14121  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14122  * the estimated probability to exceed \p threshold is less than 25 %.
14123  *
14124  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14125  * of confidence.
14126  *
14127  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14128  * at the given confidence level \p clevel.
14129  */
14131  SCIP_SET* set, /**< global SCIP settings */
14132  SCIP_STAT* stat, /**< problem statistics */
14133  SCIP_VAR* var, /**< variable x */
14134  SCIP_Real frac, /**< the fractionality of variable x */
14135  SCIP_Real threshold, /**< the threshold to test against */
14136  SCIP_BRANCHDIR dir, /**< branching direction */
14137  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14138  )
14139 {
14140  SCIP_Real mean;
14141  SCIP_Real variance;
14142  SCIP_Real count;
14143  SCIP_Real realdirection;
14144  SCIP_Real probability;
14145  SCIP_Real problimit;
14146 
14147  count = SCIPvarGetPseudocostCount(var, dir);
14148 
14149  /* if not at least 2 measurements were taken, return FALSE */
14150  if( count <= 1.9 )
14151  return FALSE;
14152 
14153  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14154 
14155  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14156  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14157 
14158  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14159  if( SCIPsetIsFeasGE(set, mean, threshold) )
14160  return FALSE;
14161 
14162  /* if there is no variance, the means are taken from a constant distribution */
14163  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14164  return SCIPsetIsFeasLT(set, mean, threshold);
14165 
14166  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14167  probability = SCIPnormalCDF(mean, variance, threshold);
14168 
14169  /* determine a probability limit corresponding to the given confidence level */
14170  switch( clevel )
14171  {
14173  problimit = 0.75;
14174  break;
14176  problimit = 0.875;
14177  break;
14179  problimit = 0.9;
14180  break;
14182  problimit = 0.95;
14183  break;
14185  problimit = 0.975;
14186  break;
14187  default:
14188  problimit = -1;
14189  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14190  SCIPABORT();
14191  break;
14192  }
14193 
14194  return (probability >= problimit);
14195 }
14196 
14197 /** find the corresponding history entry if already existing, otherwise create new entry */
14198 static
14200  SCIP_VAR* var, /**< problem variable */
14201  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14202  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14203  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14204  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14205  )
14206 {
14207  assert(var != NULL);
14208  assert(blkmem != NULL);
14209  assert(set != NULL);
14210  assert(history != NULL);
14211 
14212  (*history) = NULL;
14213 
14214  if( var->valuehistory == NULL )
14215  {
14216  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14217  }
14218 
14219  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14220 
14221  return SCIP_OKAY;
14222 }
14223 
14224 /** check if value based history should be used */
14225 static
14227  SCIP_VAR* var, /**< problem variable */
14228  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14229  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14230  )
14231 {
14232  /* check if the domain value is unknown (not specific) */
14233  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14234  return FALSE;
14235 
14236  assert(set != NULL);
14237 
14238  /* check if value based history should be collected */
14239  if( !set->history_valuebased )
14240  return FALSE;
14241 
14242  /* value based history is not collected for binary variable since the standard history already contains all information */
14243  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14244  return FALSE;
14245 
14246  /* value based history is not collected for continuous variables */
14248  return FALSE;
14249 
14250  return TRUE;
14251 }
14252 
14253 /** increases VSIDS of the variable by the given weight */
14255  SCIP_VAR* var, /**< problem variable */
14256  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14257  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14258  SCIP_STAT* stat, /**< problem statistics */
14259  SCIP_BRANCHDIR dir, /**< branching direction */
14260  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14261  SCIP_Real weight /**< weight of this update in VSIDS */
14262  )
14263 {
14264  assert(var != NULL);
14265  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14266 
14267  /* check if history statistics should be collected for a variable */
14268  if( !stat->collectvarhistory )
14269  return SCIP_OKAY;
14270 
14271  if( SCIPsetIsZero(set, weight) )
14272  return SCIP_OKAY;
14273 
14274  switch( SCIPvarGetStatus(var) )
14275  {
14277  if( var->data.original.transvar == NULL )
14278  {
14279  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14280  return SCIP_INVALIDDATA;
14281  }
14282  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14283  return SCIP_OKAY;
14284 
14285  case SCIP_VARSTATUS_LOOSE:
14286  case SCIP_VARSTATUS_COLUMN:
14287  {
14288  SCIPhistoryIncVSIDS(var->history, dir, weight);
14289  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14290 
14291  if( useValuehistory(var, value, set) )
14292  {
14293  SCIP_HISTORY* history;
14294 
14295  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14296  assert(history != NULL);
14297 
14298  SCIPhistoryIncVSIDS(history, dir, weight);
14299  SCIPdebugMessage("variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14300  value, weight, SCIPhistoryGetVSIDS(history, dir));
14301  }
14302 
14303  return SCIP_OKAY;
14304  }
14305  case SCIP_VARSTATUS_FIXED:
14306  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14307  return SCIP_INVALIDDATA;
14308 
14310  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14311 
14312  if( var->data.aggregate.scalar > 0.0 )
14313  {
14314  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14315  }
14316  else
14317  {
14318  assert(var->data.aggregate.scalar < 0.0);
14319  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14320  }
14321  return SCIP_OKAY;
14322 
14324  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14325  return SCIP_INVALIDDATA;
14326 
14328  value = 1.0 - value;
14329 
14330  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14331  return SCIP_OKAY;
14332 
14333  default:
14334  SCIPerrorMessage("unknown variable status\n");
14335  return SCIP_INVALIDDATA;
14336  }
14337 }
14338 
14339 /** scales the VSIDS of the variable by the given scalar */
14341  SCIP_VAR* var, /**< problem variable */
14342  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14343  )
14344 {
14345  assert(var != NULL);
14346 
14347  switch( SCIPvarGetStatus(var) )
14348  {
14350  if( var->data.original.transvar == NULL )
14351  {
14352  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14353  return SCIP_INVALIDDATA;
14354  }
14356  return SCIP_OKAY;
14357 
14358  case SCIP_VARSTATUS_LOOSE:
14359  case SCIP_VARSTATUS_COLUMN:
14360  {
14361  SCIPhistoryScaleVSIDS(var->history, scalar);
14362  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14364 
14365  return SCIP_OKAY;
14366  }
14367  case SCIP_VARSTATUS_FIXED:
14368  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14369  return SCIP_INVALIDDATA;
14370 
14372  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14373  return SCIP_OKAY;
14374 
14376  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14377  return SCIP_INVALIDDATA;
14378 
14380  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14381  return SCIP_OKAY;
14382 
14383  default:
14384  SCIPerrorMessage("unknown variable status\n");
14385  return SCIP_INVALIDDATA;
14386  }
14387 }
14388 
14389 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14391  SCIP_VAR* var, /**< problem variable */
14392  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14393  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14394  SCIP_STAT* stat, /**< problem statistics */
14395  SCIP_BRANCHDIR dir, /**< branching direction */
14396  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14397  SCIP_Real length /**< length of the conflict */
14398  )
14399 {
14400  assert(var != NULL);
14401  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14402 
14403  /* check if history statistics should be collected for a variable */
14404  if( !stat->collectvarhistory )
14405  return SCIP_OKAY;
14406 
14407  switch( SCIPvarGetStatus(var) )
14408  {
14410  if( var->data.original.transvar == NULL )
14411  {
14412  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14413  return SCIP_INVALIDDATA;
14414  }
14415  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14416  return SCIP_OKAY;
14417 
14418  case SCIP_VARSTATUS_LOOSE:
14419  case SCIP_VARSTATUS_COLUMN:
14420  {
14421  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14422  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14423 
14424  if( useValuehistory(var, value, set) )
14425  {
14426  SCIP_HISTORY* history;
14427 
14428  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14429  assert(history != NULL);
14430 
14431  SCIPhistoryIncNActiveConflicts(history, dir, length);
14432  }
14433 
14434  return SCIP_OKAY;
14435  }
14436  case SCIP_VARSTATUS_FIXED:
14437  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14438  return SCIP_INVALIDDATA;
14439 
14441  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14442 
14443  if( var->data.aggregate.scalar > 0.0 )
14444  {
14445  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14446  }
14447  else
14448  {
14449  assert(var->data.aggregate.scalar < 0.0);
14450  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14451  }
14452  return SCIP_OKAY;
14453 
14455  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14456  return SCIP_INVALIDDATA;
14457 
14459  value = 1.0 - value;
14460 
14461  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14462  return SCIP_OKAY;
14463 
14464  default:
14465  SCIPerrorMessage("unknown variable status\n");
14466  return SCIP_INVALIDDATA;
14467  }
14468 }
14469 
14470 /** gets the number of active conflicts containing this variable in given direction */
14472  SCIP_VAR* var, /**< problem variable */
14473  SCIP_STAT* stat, /**< problem statistics */
14474  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14475  )
14476 {
14477  assert(var != NULL);
14478  assert(stat != NULL);
14479  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14480 
14481  switch( SCIPvarGetStatus(var) )
14482  {
14484  if( var->data.original.transvar == NULL )
14485  return 0;
14486  else
14487  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14488 
14489  case SCIP_VARSTATUS_LOOSE:
14490  case SCIP_VARSTATUS_COLUMN:
14491  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14492 
14493  case SCIP_VARSTATUS_FIXED:
14494  return 0;
14495 
14497  if( var->data.aggregate.scalar > 0.0 )
14498  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14499  else
14501 
14503  return 0;
14504 
14507 
14508  default:
14509  SCIPerrorMessage("unknown variable status\n");
14510  SCIPABORT();
14511  return 0; /*lint !e527*/
14512  }
14513 }
14514 
14515 /** gets the number of active conflicts containing this variable in given direction
14516  * in the current run
14517  */
14519  SCIP_VAR* var, /**< problem variable */
14520  SCIP_STAT* stat, /**< problem statistics */
14521  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14522  )
14523 {
14524  assert(var != NULL);
14525  assert(stat != NULL);
14526  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14527 
14528  switch( SCIPvarGetStatus(var) )
14529  {
14531  if( var->data.original.transvar == NULL )
14532  return 0;
14533  else
14535 
14536  case SCIP_VARSTATUS_LOOSE:
14537  case SCIP_VARSTATUS_COLUMN:
14538  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14539 
14540  case SCIP_VARSTATUS_FIXED:
14541  return 0;
14542 
14544  if( var->data.aggregate.scalar > 0.0 )
14545  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14546  else
14548 
14550  return 0;
14551 
14554 
14555  default:
14556  SCIPerrorMessage("unknown variable status\n");
14557  SCIPABORT();
14558  return 0; /*lint !e527*/
14559  }
14560 }
14561 
14562 /** gets the average conflict length in given direction due to branching on the variable */
14564  SCIP_VAR* var, /**< problem variable */
14565  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14566  )
14567 {
14568  assert(var != NULL);
14569  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14570 
14571  switch( SCIPvarGetStatus(var) )
14572  {
14574  if( var->data.original.transvar == NULL )
14575  return 0.0;
14576  else
14578 
14579  case SCIP_VARSTATUS_LOOSE:
14580  case SCIP_VARSTATUS_COLUMN:
14581  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14582  case SCIP_VARSTATUS_FIXED:
14583  return 0.0;
14584 
14586  if( var->data.aggregate.scalar > 0.0 )
14587  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14588  else
14590 
14592  return 0.0;
14593 
14596 
14597  default:
14598  SCIPerrorMessage("unknown variable status\n");
14599  SCIPABORT();
14600  return 0.0; /*lint !e527*/
14601  }
14602 }
14603 
14604 /** gets the average conflict length in given direction due to branching on the variable
14605  * in the current run
14606  */
14608  SCIP_VAR* var, /**< problem variable */
14609  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14610  )
14611 {
14612  assert(var != NULL);
14613  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14614 
14615  switch( SCIPvarGetStatus(var) )
14616  {
14618  if( var->data.original.transvar == NULL )
14619  return 0.0;
14620  else
14622 
14623  case SCIP_VARSTATUS_LOOSE:
14624  case SCIP_VARSTATUS_COLUMN:
14625  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14626 
14627  case SCIP_VARSTATUS_FIXED:
14628  return 0.0;
14629 
14631  if( var->data.aggregate.scalar > 0.0 )
14633  else
14635 
14637  return 0.0;
14638 
14641 
14642  default:
14643  SCIPerrorMessage("unknown variable status\n");
14644  SCIPABORT();
14645  return 0.0; /*lint !e527*/
14646  }
14647 }
14648 
14649 /** increases the number of branchings counter of the variable */
14651  SCIP_VAR* var, /**< problem variable */
14652  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14653  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14654  SCIP_STAT* stat, /**< problem statistics */
14655  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14656  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14657  int depth /**< depth at which the bound change took place */
14658  )
14659 {
14660  assert(var != NULL);
14661  assert(stat != NULL);
14662  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14663 
14664  /* check if history statistics should be collected for a variable */
14665  if( !stat->collectvarhistory )
14666  return SCIP_OKAY;
14667 
14668  switch( SCIPvarGetStatus(var) )
14669  {
14671  if( var->data.original.transvar == NULL )
14672  {
14673  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14674  return SCIP_INVALIDDATA;
14675  }
14676  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14677  return SCIP_OKAY;
14678 
14679  case SCIP_VARSTATUS_LOOSE:
14680  case SCIP_VARSTATUS_COLUMN:
14681  {
14682  SCIPhistoryIncNBranchings(var->history, dir, depth);
14683  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14684  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14685  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14686 
14687  if( useValuehistory(var, value, set) )
14688  {
14689  SCIP_HISTORY* history;
14690 
14691  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14692  assert(history != NULL);
14693 
14694  SCIPhistoryIncNBranchings(history, dir, depth);
14695  }
14696 
14697  return SCIP_OKAY;
14698  }
14699  case SCIP_VARSTATUS_FIXED:
14700  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14701  return SCIP_INVALIDDATA;
14702 
14704  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14705 
14706  if( var->data.aggregate.scalar > 0.0 )
14707  {
14708  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14709  }
14710  else
14711  {
14712  assert(var->data.aggregate.scalar < 0.0);
14713  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14714  }
14715  return SCIP_OKAY;
14716 
14718  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14719  return SCIP_INVALIDDATA;
14720 
14722  value = 1.0 - value;
14723 
14724  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14725  return SCIP_OKAY;
14726 
14727  default:
14728  SCIPerrorMessage("unknown variable status\n");
14729  return SCIP_INVALIDDATA;
14730  }
14731 }
14732 
14733 /** increases the inference sum of the variable by the given weight */
14735  SCIP_VAR* var, /**< problem variable */
14736  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14737  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14738  SCIP_STAT* stat, /**< problem statistics */
14739  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14740  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14741  SCIP_Real weight /**< weight of this update in inference score */
14742  )
14743 {
14744  assert(var != NULL);
14745  assert(stat != NULL);
14746  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14747 
14748  /* check if history statistics should be collected for a variable */
14749  if( !stat->collectvarhistory )
14750  return SCIP_OKAY;
14751 
14752  switch( SCIPvarGetStatus(var) )
14753  {
14755  if( var->data.original.transvar == NULL )
14756  {
14757  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
14758  return SCIP_INVALIDDATA;
14759  }
14760  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14761  return SCIP_OKAY;
14762 
14763  case SCIP_VARSTATUS_LOOSE:
14764  case SCIP_VARSTATUS_COLUMN:
14765  {
14766  SCIPhistoryIncInferenceSum(var->history, dir, weight);
14767  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
14768  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
14769  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
14770 
14771  if( useValuehistory(var, value, set) )
14772  {
14773  SCIP_HISTORY* history;
14774 
14775  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14776  assert(history != NULL);
14777 
14778  SCIPhistoryIncInferenceSum(history, dir, weight);
14779  }
14780 
14781  return SCIP_OKAY;
14782  }
14783  case SCIP_VARSTATUS_FIXED:
14784  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
14785  return SCIP_INVALIDDATA;
14786 
14788  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14789 
14790  if( var->data.aggregate.scalar > 0.0 )
14791  {
14792  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14793  }
14794  else
14795  {
14796  assert(var->data.aggregate.scalar < 0.0);
14797  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14798  }
14799  return SCIP_OKAY;
14800 
14802  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
14803  return SCIP_INVALIDDATA;
14804 
14806  value = 1.0 - value;
14807 
14808  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14809  return SCIP_OKAY;
14810 
14811  default:
14812  SCIPerrorMessage("unknown variable status\n");
14813  return SCIP_INVALIDDATA;
14814  }
14815 }
14816 
14817 /** increases the cutoff sum of the variable by the given weight */
14819  SCIP_VAR* var, /**< problem variable */
14820  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14821  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14822  SCIP_STAT* stat, /**< problem statistics */
14823  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14824  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14825  SCIP_Real weight /**< weight of this update in cutoff score */
14826  )
14827 {
14828  assert(var != NULL);
14829  assert(stat != NULL);
14830  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14831 
14832  /* check if history statistics should be collected for a variable */
14833  if( !stat->collectvarhistory )
14834  return SCIP_OKAY;
14835 
14836  switch( SCIPvarGetStatus(var) )
14837  {
14839  if( var->data.original.transvar == NULL )
14840  {
14841  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
14842  return SCIP_INVALIDDATA;
14843  }
14844  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14845  return SCIP_OKAY;
14846 
14847  case SCIP_VARSTATUS_LOOSE:
14848  case SCIP_VARSTATUS_COLUMN:
14849  {
14850  SCIPhistoryIncCutoffSum(var->history, dir, weight);
14851  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
14852  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
14853  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
14854 
14855  if( useValuehistory(var, value, set) )
14856  {
14857  SCIP_HISTORY* history;
14858 
14859  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14860  assert(history != NULL);
14861 
14862  SCIPhistoryIncCutoffSum(history, dir, weight);
14863  }
14864 
14865  return SCIP_OKAY;
14866  }
14867  case SCIP_VARSTATUS_FIXED:
14868  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
14869  return SCIP_INVALIDDATA;
14870 
14872  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14873 
14874  if( var->data.aggregate.scalar > 0.0 )
14875  {
14876  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14877  }
14878  else
14879  {
14880  assert(var->data.aggregate.scalar < 0.0);
14881  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14882  }
14883  return SCIP_OKAY;
14884 
14886  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
14887  return SCIP_INVALIDDATA;
14888 
14890  value = 1.0 - value;
14891 
14892  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14893  return SCIP_OKAY;
14894 
14895  default:
14896  SCIPerrorMessage("unknown variable status\n");
14897  return SCIP_INVALIDDATA;
14898  }
14899 }
14900 
14901 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
14903  SCIP_VAR* var, /**< problem variable */
14904  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14905  )
14906 {
14907  assert(var != NULL);
14908  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14909 
14910  switch( SCIPvarGetStatus(var) )
14911  {
14913  if( var->data.original.transvar == NULL )
14914  return 0;
14915  else
14916  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
14917 
14918  case SCIP_VARSTATUS_LOOSE:
14919  case SCIP_VARSTATUS_COLUMN:
14920  return SCIPhistoryGetNBranchings(var->history, dir);
14921 
14922  case SCIP_VARSTATUS_FIXED:
14923  return 0;
14924 
14926  if( var->data.aggregate.scalar > 0.0 )
14927  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
14928  else
14930 
14932  return 0;
14933 
14936 
14937  default:
14938  SCIPerrorMessage("unknown variable status\n");
14939  SCIPABORT();
14940  return 0; /*lint !e527*/
14941  }
14942 }
14943 
14944 /** returns the number of times, a bound of the variable was changed in given direction due to branching
14945  * in the current run
14946  */
14948  SCIP_VAR* var, /**< problem variable */
14949  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14950  )
14951 {
14952  assert(var != NULL);
14953  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14954 
14955  switch( SCIPvarGetStatus(var) )
14956  {
14958  if( var->data.original.transvar == NULL )
14959  return 0;
14960  else
14962 
14963  case SCIP_VARSTATUS_LOOSE:
14964  case SCIP_VARSTATUS_COLUMN:
14965  return SCIPhistoryGetNBranchings(var->historycrun, dir);
14966 
14967  case SCIP_VARSTATUS_FIXED:
14968  return 0;
14969 
14971  if( var->data.aggregate.scalar > 0.0 )
14973  else
14975 
14977  return 0;
14978 
14981 
14982  default:
14983  SCIPerrorMessage("unknown variable status\n");
14984  SCIPABORT();
14985  return 0; /*lint !e527*/
14986  }
14987 }
14988 
14989 /** returns the average depth of bound changes in given direction due to branching on the variable */
14991  SCIP_VAR* var, /**< problem variable */
14992  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14993  )
14994 {
14995  assert(var != NULL);
14996  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14997 
14998  switch( SCIPvarGetStatus(var) )
14999  {
15001  if( var->data.original.transvar == NULL )
15002  return 0.0;
15003  else
15004  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15005 
15006  case SCIP_VARSTATUS_LOOSE:
15007  case SCIP_VARSTATUS_COLUMN:
15008  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15009 
15010  case SCIP_VARSTATUS_FIXED:
15011  return 0.0;
15012 
15014  if( var->data.aggregate.scalar > 0.0 )
15015  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15016  else
15018 
15020  return 0.0;
15021 
15024 
15025  default:
15026  SCIPerrorMessage("unknown variable status\n");
15027  SCIPABORT();
15028  return 0.0; /*lint !e527*/
15029  }
15030 }
15031 
15032 /** returns the average depth of bound changes in given direction due to branching on the variable
15033  * in the current run
15034  */
15036  SCIP_VAR* var, /**< problem variable */
15037  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15038  )
15039 {
15040  assert(var != NULL);
15041  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15042 
15043  switch( SCIPvarGetStatus(var) )
15044  {
15046  if( var->data.original.transvar == NULL )
15047  return 0.0;
15048  else
15050 
15051  case SCIP_VARSTATUS_LOOSE:
15052  case SCIP_VARSTATUS_COLUMN:
15053  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15054 
15055  case SCIP_VARSTATUS_FIXED:
15056  return 0.0;
15057 
15059  if( var->data.aggregate.scalar > 0.0 )
15061  else
15064 
15066  return 0.0;
15067 
15070  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15071 
15072  default:
15073  SCIPerrorMessage("unknown variable status\n");
15074  SCIPABORT();
15075  return 0.0; /*lint !e527*/
15076  }
15077 }
15078 
15079 /** returns the variable's VSIDS score */
15081  SCIP_VAR* var, /**< problem variable */
15082  SCIP_STAT* stat, /**< problem statistics */
15083  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15084  )
15085 {
15086  assert(var != NULL);
15087  assert(stat != NULL);
15088  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15089 
15091  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15092 
15093  switch( SCIPvarGetStatus(var) )
15094  {
15096  if( var->data.original.transvar == NULL )
15097  return 0.0;
15098  else
15099  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15100 
15101  case SCIP_VARSTATUS_LOOSE:
15102  case SCIP_VARSTATUS_COLUMN:
15103  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15104  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15105 
15106  case SCIP_VARSTATUS_FIXED:
15107  return 0.0;
15108 
15110  if( var->data.aggregate.scalar > 0.0 )
15111  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15112  else
15113  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15114 
15116  return 0.0;
15117 
15119  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15120 
15121  default:
15122  SCIPerrorMessage("unknown variable status\n");
15123  SCIPABORT();
15124  return 0.0; /*lint !e527*/
15125  }
15126 }
15127 
15128 /** returns the variable's VSIDS score only using conflicts of the current run */
15130  SCIP_VAR* var, /**< problem variable */
15131  SCIP_STAT* stat, /**< problem statistics */
15132  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15133  )
15134 {
15135  assert(var != NULL);
15136  assert(stat != NULL);
15137  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15138 
15139  switch( SCIPvarGetStatus(var) )
15140  {
15142  if( var->data.original.transvar == NULL )
15143  return 0.0;
15144  else
15145  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15146 
15147  case SCIP_VARSTATUS_LOOSE:
15148  case SCIP_VARSTATUS_COLUMN:
15149  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15150 
15151  case SCIP_VARSTATUS_FIXED:
15152  return 0.0;
15153 
15155  if( var->data.aggregate.scalar > 0.0 )
15156  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15157  else
15159 
15161  return 0.0;
15162 
15165 
15166  default:
15167  SCIPerrorMessage("unknown variable status\n");
15168  SCIPABORT();
15169  return 0.0; /*lint !e527*/
15170  }
15171 }
15172 
15173 /** returns the number of inferences branching on this variable in given direction triggered */
15175  SCIP_VAR* var, /**< problem variable */
15176  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15177  )
15178 {
15179  assert(var != NULL);
15180  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15181 
15182  switch( SCIPvarGetStatus(var) )
15183  {
15185  if( var->data.original.transvar == NULL )
15186  return 0.0;
15187  else
15188  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15189 
15190  case SCIP_VARSTATUS_LOOSE:
15191  case SCIP_VARSTATUS_COLUMN:
15192  return SCIPhistoryGetInferenceSum(var->history, dir);
15193 
15194  case SCIP_VARSTATUS_FIXED:
15195  return 0.0;
15196 
15198  if( var->data.aggregate.scalar > 0.0 )
15199  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15200  else
15202 
15204  return 0.0;
15205 
15208 
15209  default:
15210  SCIPerrorMessage("unknown variable status\n");
15211  SCIPABORT();
15212  return 0.0; /*lint !e527*/
15213  }
15214 }
15215 
15216 /** returns the number of inferences branching on this variable in given direction triggered
15217  * in the current run
15218  */
15220  SCIP_VAR* var, /**< problem variable */
15221  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15222  )
15223 {
15224  assert(var != NULL);
15225  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15226 
15227  switch( SCIPvarGetStatus(var) )
15228  {
15230  if( var->data.original.transvar == NULL )
15231  return 0.0;
15232  else
15234 
15235  case SCIP_VARSTATUS_LOOSE:
15236  case SCIP_VARSTATUS_COLUMN:
15237  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15238 
15239  case SCIP_VARSTATUS_FIXED:
15240  return 0.0;
15241 
15243  if( var->data.aggregate.scalar > 0.0 )
15245  else
15247 
15249  return 0.0;
15250 
15253 
15254  default:
15255  SCIPerrorMessage("unknown variable status\n");
15256  SCIPABORT();
15257  return 0.0; /*lint !e527*/
15258  }
15259 }
15260 
15261 /** returns the average number of inferences found after branching on the variable in given direction */
15263  SCIP_VAR* var, /**< problem variable */
15264  SCIP_STAT* stat, /**< problem statistics */
15265  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15266  )
15267 {
15268  assert(var != NULL);
15269  assert(stat != NULL);
15270  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15271 
15272  switch( SCIPvarGetStatus(var) )
15273  {
15275  if( var->data.original.transvar == NULL )
15276  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15277  else
15278  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15279 
15280  case SCIP_VARSTATUS_LOOSE:
15281  case SCIP_VARSTATUS_COLUMN:
15282  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15283  return SCIPhistoryGetAvgInferences(var->history, dir);
15284  else
15285  {
15286  int nimpls;
15287  int ncliques;
15288 
15289  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15290  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15291  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15292  }
15293 
15294  case SCIP_VARSTATUS_FIXED:
15295  return 0.0;
15296 
15298  if( var->data.aggregate.scalar > 0.0 )
15299  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15300  else
15302 
15304  return 0.0;
15305 
15307  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15308 
15309  default:
15310  SCIPerrorMessage("unknown variable status\n");
15311  SCIPABORT();
15312  return 0.0; /*lint !e527*/
15313  }
15314 }
15315 
15316 /** returns the average number of inferences found after branching on the variable in given direction
15317  * in the current run
15318  */
15320  SCIP_VAR* var, /**< problem variable */
15321  SCIP_STAT* stat, /**< problem statistics */
15322  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15323  )
15324 {
15325  assert(var != NULL);
15326  assert(stat != NULL);
15327  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15328 
15329  switch( SCIPvarGetStatus(var) )
15330  {
15332  if( var->data.original.transvar == NULL )
15333  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15334  else
15335  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15336 
15337  case SCIP_VARSTATUS_LOOSE:
15338  case SCIP_VARSTATUS_COLUMN:
15339  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15340  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15341  else
15342  {
15343  int nimpls;
15344  int ncliques;
15345 
15346  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15347  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15348  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15349  }
15350 
15351  case SCIP_VARSTATUS_FIXED:
15352  return 0.0;
15353 
15355  if( var->data.aggregate.scalar > 0.0 )
15356  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15357  else
15359 
15361  return 0.0;
15362 
15365 
15366  default:
15367  SCIPerrorMessage("unknown variable status\n");
15368  SCIPABORT();
15369  return 0.0; /*lint !e527*/
15370  }
15371 }
15372 
15373 /** returns the number of cutoffs branching on this variable in given direction produced */
15375  SCIP_VAR* var, /**< problem variable */
15376  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15377  )
15378 {
15379  assert(var != NULL);
15380  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15381 
15382  switch( SCIPvarGetStatus(var) )
15383  {
15385  if( var->data.original.transvar == NULL )
15386  return 0;
15387  else
15388  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15389 
15390  case SCIP_VARSTATUS_LOOSE:
15391  case SCIP_VARSTATUS_COLUMN:
15392  return SCIPhistoryGetCutoffSum(var->history, dir);
15393 
15394  case SCIP_VARSTATUS_FIXED:
15395  return 0;
15396 
15398  if( var->data.aggregate.scalar > 0.0 )
15399  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15400  else
15402 
15404  return 0;
15405 
15408 
15409  default:
15410  SCIPerrorMessage("unknown variable status\n");
15411  SCIPABORT();
15412  return 0; /*lint !e527*/
15413  }
15414 }
15415 
15416 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15418  SCIP_VAR* var, /**< problem variable */
15419  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15420  )
15421 {
15422  assert(var != NULL);
15423  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15424 
15425  switch( SCIPvarGetStatus(var) )
15426  {
15428  if( var->data.original.transvar == NULL )
15429  return 0;
15430  else
15432 
15433  case SCIP_VARSTATUS_LOOSE:
15434  case SCIP_VARSTATUS_COLUMN:
15435  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15436 
15437  case SCIP_VARSTATUS_FIXED:
15438  return 0;
15439 
15441  if( var->data.aggregate.scalar > 0.0 )
15442  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15443  else
15445 
15447  return 0;
15448 
15451 
15452  default:
15453  SCIPerrorMessage("unknown variable status\n");
15454  SCIPABORT();
15455  return 0; /*lint !e527*/
15456  }
15457 }
15458 
15459 /** returns the average number of cutoffs found after branching on the variable in given direction */
15461  SCIP_VAR* var, /**< problem variable */
15462  SCIP_STAT* stat, /**< problem statistics */
15463  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15464  )
15465 {
15466  assert(var != NULL);
15467  assert(stat != NULL);
15468  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15469 
15470  switch( SCIPvarGetStatus(var) )
15471  {
15473  if( var->data.original.transvar == NULL )
15474  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15475  else
15476  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15477 
15478  case SCIP_VARSTATUS_LOOSE:
15479  case SCIP_VARSTATUS_COLUMN:
15480  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15481  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15482  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15483 
15484  case SCIP_VARSTATUS_FIXED:
15485  return 0.0;
15486 
15488  if( var->data.aggregate.scalar > 0.0 )
15489  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15490  else
15491  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15492 
15494  return 0.0;
15495 
15497  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15498 
15499  default:
15500  SCIPerrorMessage("unknown variable status\n");
15501  SCIPABORT();
15502  return 0.0; /*lint !e527*/
15503  }
15504 }
15505 
15506 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15508  SCIP_VAR* var, /**< problem variable */
15509  SCIP_STAT* stat, /**< problem statistics */
15510  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15511  )
15512 {
15513  assert(var != NULL);
15514  assert(stat != NULL);
15515  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15516 
15517  switch( SCIPvarGetStatus(var) )
15518  {
15520  if( var->data.original.transvar == NULL )
15521  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15522  else
15523  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15524 
15525  case SCIP_VARSTATUS_LOOSE:
15526  case SCIP_VARSTATUS_COLUMN:
15527  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15530 
15531  case SCIP_VARSTATUS_FIXED:
15532  return 0.0;
15533 
15535  if( var->data.aggregate.scalar > 0.0 )
15536  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15537  else
15539 
15541  return 0.0;
15542 
15545 
15546  default:
15547  SCIPerrorMessage("unknown variable status\n");
15548  SCIPABORT();
15549  return 0.0; /*lint !e527*/
15550  }
15551 }
15552 
15553 
15554 
15555 
15556 /*
15557  * information methods for bound changes
15558  */
15559 
15560 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15562  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15563  BMS_BLKMEM* blkmem, /**< block memory */
15564  SCIP_VAR* var, /**< active variable that changed the bounds */
15565  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15566  SCIP_Real oldbound, /**< old value for bound */
15567  SCIP_Real newbound /**< new value for bound */
15568  )
15569 {
15570  assert(bdchginfo != NULL);
15571 
15572  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15573  (*bdchginfo)->oldbound = oldbound;
15574  (*bdchginfo)->newbound = newbound;
15575  (*bdchginfo)->var = var;
15576  (*bdchginfo)->inferencedata.var = var;
15577  (*bdchginfo)->inferencedata.reason.prop = NULL;
15578  (*bdchginfo)->inferencedata.info = 0;
15579  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15580  (*bdchginfo)->bdchgidx.pos = -1;
15581  (*bdchginfo)->pos = 0;
15582  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15583  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15584  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15585  (*bdchginfo)->redundant = FALSE;
15586 
15587  return SCIP_OKAY;
15588 }
15589 
15590 /** frees a bound change information object */
15591 void SCIPbdchginfoFree(
15592  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15593  BMS_BLKMEM* blkmem /**< block memory */
15594  )
15595 {
15596  assert(bdchginfo != NULL);
15597 
15598  BMSfreeBlockMemory(blkmem, bdchginfo);
15599 }
15600 
15601 /** returns the bound change information for the last lower bound change on given active problem variable before or
15602  * after the bound change with the given index was applied;
15603  * returns NULL, if no change to the lower bound was applied up to this point of time
15604  */
15606  SCIP_VAR* var, /**< active problem variable */
15607  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15608  SCIP_Bool after /**< should the bound change with given index be included? */
15609  )
15610 {
15611  int i;
15612 
15613  assert(var != NULL);
15614  assert(SCIPvarIsActive(var));
15615 
15616  /* search the correct bound change information for the given bound change index */
15617  if( after )
15618  {
15619  for( i = var->nlbchginfos-1; i >= 0; --i )
15620  {
15621  assert(var->lbchginfos[i].var == var);
15623  assert(var->lbchginfos[i].pos == i);
15624 
15625  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15626  if( var->lbchginfos[i].redundant )
15627  return NULL;
15628  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15629 
15630  /* if we reached the bound change index, return the current bound change info */
15631  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15632  return &var->lbchginfos[i];
15633  }
15634  }
15635  else
15636  {
15637  for( i = var->nlbchginfos-1; i >= 0; --i )
15638  {
15639  assert(var->lbchginfos[i].var == var);
15641  assert(var->lbchginfos[i].pos == i);
15642 
15643  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15644  if( var->lbchginfos[i].redundant )
15645  return NULL;
15646  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15647 
15648  /* if we reached the bound change index, return the current bound change info */
15649  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15650  return &var->lbchginfos[i];
15651  }
15652  }
15653 
15654  return NULL;
15655 }
15656 
15657 /** returns the bound change information for the last upper bound change on given active problem variable before or
15658  * after the bound change with the given index was applied;
15659  * returns NULL, if no change to the upper bound was applied up to this point of time
15660  */
15662  SCIP_VAR* var, /**< active problem variable */
15663  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15664  SCIP_Bool after /**< should the bound change with given index be included? */
15665  )
15666 {
15667  int i;
15668 
15669  assert(var != NULL);
15670  assert(SCIPvarIsActive(var));
15671 
15672  /* search the correct bound change information for the given bound change index */
15673  if( after )
15674  {
15675  for( i = var->nubchginfos-1; i >= 0; --i )
15676  {
15677  assert(var->ubchginfos[i].var == var);
15679  assert(var->ubchginfos[i].pos == i);
15680 
15681  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15682  if( var->ubchginfos[i].redundant )
15683  return NULL;
15684  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15685 
15686  /* if we reached the bound change index, return the current bound change info */
15687  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15688  return &var->ubchginfos[i];
15689  }
15690  }
15691  else
15692  {
15693  for( i = var->nubchginfos-1; i >= 0; --i )
15694  {
15695  assert(var->ubchginfos[i].var == var);
15697  assert(var->ubchginfos[i].pos == i);
15698 
15699  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15700  if( var->ubchginfos[i].redundant )
15701  return NULL;
15702  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15703 
15704  /* if we reached the bound change index, return the current bound change info */
15705  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15706  return &var->ubchginfos[i];
15707  }
15708  }
15709 
15710  return NULL;
15711 }
15712 
15713 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15714  * before or after the bound change with the given index was applied;
15715  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15716  */
15718  SCIP_VAR* var, /**< active problem variable */
15719  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15720  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15721  SCIP_Bool after /**< should the bound change with given index be included? */
15722  )
15723 {
15724  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15725  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
15726  else
15727  {
15728  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15729  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
15730  }
15731 }
15732 
15733 /** returns lower bound of variable directly before or after the bound change given by the bound change index
15734  * was applied
15735  */
15737  SCIP_VAR* var, /**< problem variable */
15738  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15739  SCIP_Bool after /**< should the bound change with given index be included? */
15740  )
15741 {
15742  SCIP_VARSTATUS varstatus;
15743  assert(var != NULL);
15744 
15745  varstatus = SCIPvarGetStatus(var);
15746 
15747  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15748  {
15749  if( bdchgidx == NULL )
15750  return SCIPvarGetLbLocal(var);
15751  else
15752  {
15753  SCIP_BDCHGINFO* bdchginfo;
15754 
15755  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
15756  if( bdchginfo != NULL )
15757  return SCIPbdchginfoGetNewbound(bdchginfo);
15758  else
15759  return var->glbdom.lb;
15760  }
15761  }
15762 
15763  /* get bounds of attached variables */
15764  switch( varstatus )
15765  {
15767  assert(var->data.original.transvar != NULL);
15768  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
15769 
15770  case SCIP_VARSTATUS_FIXED:
15771  return var->glbdom.lb;
15772 
15773  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15774  assert(var->data.aggregate.var != NULL);
15775  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15776  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15777  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15778  * (or is called by) a public interface method; instead, we only assert that values are finite
15779  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15780  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15781  */
15782  if( var->data.aggregate.scalar > 0.0 )
15783  {
15784  /* a > 0 -> get lower bound of y */
15785  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15786  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15787  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15788  + var->data.aggregate.constant;
15789  }
15790  else if( var->data.aggregate.scalar < 0.0 )
15791  {
15792  /* a < 0 -> get upper bound of y */
15793  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15794  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15795  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15796  + var->data.aggregate.constant;
15797  }
15798  else
15799  {
15800  SCIPerrorMessage("scalar is zero in aggregation\n");
15801  SCIPABORT();
15802  return SCIP_INVALID; /*lint !e527*/
15803  }
15804 
15806  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
15807  if ( var->data.multaggr.nvars == 1 )
15808  {
15809  assert(var->data.multaggr.vars != NULL);
15810  assert(var->data.multaggr.scalars != NULL);
15811  assert(var->data.multaggr.vars[0] != NULL);
15812 
15813  if( var->data.multaggr.scalars[0] > 0.0 )
15814  {
15815  /* a > 0 -> get lower bound of y */
15816  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15817  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15818  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15819  + var->data.multaggr.constant;
15820  }
15821  else if( var->data.multaggr.scalars[0] < 0.0 )
15822  {
15823  /* a < 0 -> get upper bound of y */
15824  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15825  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15826  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15827  + var->data.multaggr.constant;
15828  }
15829  else
15830  {
15831  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
15832  SCIPABORT();
15833  return SCIP_INVALID; /*lint !e527*/
15834  }
15835  }
15836  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
15837  SCIPABORT();
15838  return SCIP_INVALID; /*lint !e527*/
15839 
15840  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15841  assert(var->negatedvar != NULL);
15843  assert(var->negatedvar->negatedvar == var);
15844  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
15845 
15846  case SCIP_VARSTATUS_COLUMN: /* for lint */
15847  case SCIP_VARSTATUS_LOOSE: /* for lint */
15848  default:
15849  SCIPerrorMessage("unknown variable status\n");
15850  SCIPABORT();
15851  return SCIP_INVALID; /*lint !e527*/
15852  }
15853 }
15854 
15855 /** returns upper bound of variable directly before or after the bound change given by the bound change index
15856  * was applied
15857  */
15859  SCIP_VAR* var, /**< problem variable */
15860  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15861  SCIP_Bool after /**< should the bound change with given index be included? */
15862  )
15863 {
15864  SCIP_VARSTATUS varstatus;
15865  assert(var != NULL);
15866 
15867  varstatus = SCIPvarGetStatus(var);
15868 
15869  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15870  {
15871  if( bdchgidx == NULL )
15872  return SCIPvarGetUbLocal(var);
15873  else
15874  {
15875  SCIP_BDCHGINFO* bdchginfo;
15876 
15877  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
15878  if( bdchginfo != NULL )
15879  return SCIPbdchginfoGetNewbound(bdchginfo);
15880  else
15881  return var->glbdom.ub;
15882  }
15883  }
15884 
15885  /* get bounds of attached variables */
15886  switch( varstatus )
15887  {
15889  assert(var->data.original.transvar != NULL);
15890  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
15891 
15892  case SCIP_VARSTATUS_FIXED:
15893  return var->glbdom.ub;
15894 
15895  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15896  assert(var->data.aggregate.var != NULL);
15897  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15898  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15899  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15900  * (or is called by) a public interface method; instead, we only assert that values are finite
15901  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15902  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15903  */
15904  if( var->data.aggregate.scalar > 0.0 )
15905  {
15906  /* a > 0 -> get lower bound of y */
15907  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15908  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15909  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15910  + var->data.aggregate.constant;
15911  }
15912  else if( var->data.aggregate.scalar < 0.0 )
15913  {
15914  /* a < 0 -> get upper bound of y */
15915  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15916  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15917  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15918  + var->data.aggregate.constant;
15919  }
15920  else
15921  {
15922  SCIPerrorMessage("scalar is zero in aggregation\n");
15923  SCIPABORT();
15924  return SCIP_INVALID; /*lint !e527*/
15925  }
15926 
15928  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
15929  if ( var->data.multaggr.nvars == 1 )
15930  {
15931  assert(var->data.multaggr.vars != NULL);
15932  assert(var->data.multaggr.scalars != NULL);
15933  assert(var->data.multaggr.vars[0] != NULL);
15934 
15935  if( var->data.multaggr.scalars[0] > 0.0 )
15936  {
15937  /* a > 0 -> get lower bound of y */
15938  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15939  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15940  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15941  + var->data.multaggr.constant;
15942  }
15943  else if( var->data.multaggr.scalars[0] < 0.0 )
15944  {
15945  /* a < 0 -> get upper bound of y */
15946  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15947  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15948  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15949  + var->data.multaggr.constant;
15950  }
15951  else
15952  {
15953  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
15954  SCIPABORT();
15955  return SCIP_INVALID; /*lint !e527*/
15956  }
15957  }
15958  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
15959  SCIPABORT();
15960  return SCIP_INVALID; /*lint !e527*/
15961 
15962  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15963  assert(var->negatedvar != NULL);
15965  assert(var->negatedvar->negatedvar == var);
15966  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
15967 
15968  case SCIP_VARSTATUS_COLUMN: /* for lint */
15969  case SCIP_VARSTATUS_LOOSE: /* for lint */
15970  default:
15971  SCIPerrorMessage("unknown variable status\n");
15972  SCIPABORT();
15973  return SCIP_INVALID; /*lint !e527*/
15974  }
15975 }
15976 
15977 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
15978  * was applied
15979  */
15981  SCIP_VAR* var, /**< problem variable */
15982  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15983  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15984  SCIP_Bool after /**< should the bound change with given index be included? */
15985  )
15986 {
15987  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15988  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
15989  else
15990  {
15991  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15992  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
15993  }
15994 }
15995 
15996 /** returns whether the binary variable was fixed at the time given by the bound change index */
15998  SCIP_VAR* var, /**< problem variable */
15999  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16000  SCIP_Bool after /**< should the bound change with given index be included? */
16001  )
16002 {
16003  assert(var != NULL);
16004  assert(SCIPvarIsBinary(var));
16005 
16006  /* check the current bounds first in order to decide at which bound change information we have to look
16007  * (which is expensive because we have to follow the aggregation tree to the active variable)
16008  */
16009  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16010  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16011 }
16012 
16013 /** bound change index representing the initial time before any bound changes took place */
16014 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16016 /** bound change index representing the presolving stage */
16017 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16019 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16021  SCIP_VAR* var /**< problem variable */
16022  )
16023 {
16024  SCIP_BDCHGIDX* lbchgidx;
16025  SCIP_BDCHGIDX* ubchgidx;
16026 
16027  assert(var != NULL);
16028 
16029  var = SCIPvarGetProbvar(var);
16030 
16031  /* check, if variable is original without transformed variable */
16032  if( var == NULL )
16033  return &initbdchgidx;
16034 
16035  /* check, if variable was fixed in presolving */
16036  if( !SCIPvarIsActive(var) )
16037  return &presolvebdchgidx;
16038 
16040 
16041  /* get depths of last bound change information for the lower and upper bound */
16042  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16043  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16044  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16045  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16046 
16047  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16048  return ubchgidx;
16049  else
16050  return lbchgidx;
16051 }
16052 
16053 /** returns the last depth level, at which the bounds of the given variable were tightened;
16054  * returns -2, if the variable's bounds are still the global bounds
16055  * returns -1, if the variable was fixed in presolving
16056  */
16058  SCIP_VAR* var /**< problem variable */
16059  )
16060 {
16061  SCIP_BDCHGIDX* bdchgidx;
16062 
16063  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16064  assert(bdchgidx != NULL);
16065 
16066  return bdchgidx->depth;
16067 }
16068 
16069 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16070  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16071  */
16073  SCIP_VAR* var, /**< problem variable */
16074  SCIP_SET* set, /**< global SCIP settings */
16075  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16076  SCIP_Real bound /**< conflicting bound */
16077  )
16078 {
16079  int i;
16080 
16081  assert(var != NULL);
16082  assert(set != NULL);
16083  assert(var->scip == set->scip);
16084 
16085  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16086  {
16087  /* check if the bound is in conflict with the current local bounds */
16088  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16089  return -1;
16090 
16091  /* check if the bound is in conflict with the global bound */
16092  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16093  return 0;
16094 
16095  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16096  assert(var->nubchginfos > 0);
16097  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16098 
16099  /* search for the first conflicting bound change */
16100  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16101  {
16102  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16104  }
16105  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16106  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16107 
16108  /* return the depth at which the first conflicting bound change took place */
16109  return var->ubchginfos[i].bdchgidx.depth;
16110  }
16111  else
16112  {
16113  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16114 
16115  /* check if the bound is in conflict with the current local bounds */
16116  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16117  return -1;
16118 
16119  /* check if the bound is in conflict with the global bound */
16120  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16121  return 0;
16122 
16123  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16124  assert(var->nlbchginfos > 0);
16125  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16126 
16127  /* search for the first conflicting bound change */
16128  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16129  {
16130  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16132  }
16133  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16134  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16135 
16136  /* return the depth at which the first conflicting bound change took place */
16137  return var->lbchginfos[i].bdchgidx.depth;
16138  }
16139 }
16140 
16141 /** returns whether the first binary variable was fixed earlier than the second one;
16142  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16143  * second one is not fixed
16144  */
16146  SCIP_VAR* var1, /**< first binary variable */
16147  SCIP_VAR* var2 /**< second binary variable */
16148  )
16149 {
16150  SCIP_BDCHGIDX* bdchgidx1;
16151  SCIP_BDCHGIDX* bdchgidx2;
16152 
16153  assert(var1 != NULL);
16154  assert(var2 != NULL);
16155  assert(SCIPvarIsBinary(var1));
16156  assert(SCIPvarIsBinary(var2));
16157 
16158  var1 = SCIPvarGetProbvar(var1);
16159  var2 = SCIPvarGetProbvar(var2);
16160  assert(var1 != NULL);
16161  assert(var2 != NULL);
16162 
16163  /* check, if variables are globally fixed */
16164  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16165  return FALSE;
16166  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16167  return TRUE;
16168 
16171  assert(SCIPvarIsBinary(var1));
16172  assert(SCIPvarIsBinary(var2));
16173  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16174  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16175  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16176  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16177  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16178  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16179 
16180  if( var1->nlbchginfos == 1 )
16181  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16182  else if( var1->nubchginfos == 1 )
16183  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16184  else
16185  bdchgidx1 = NULL;
16186 
16187  if( var2->nlbchginfos == 1 )
16188  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16189  else if( var2->nubchginfos == 1 )
16190  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16191  else
16192  bdchgidx2 = NULL;
16193 
16194  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16195 }
16196 
16197 
16198 
16199 /*
16200  * Hash functions
16201  */
16202 
16203 /** gets the key (i.e. the name) of the given variable */
16204 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16205 { /*lint --e{715}*/
16206  SCIP_VAR* var = (SCIP_VAR*)elem;
16207 
16208  assert(var != NULL);
16209  return var->name;
16210 }
16211 
16212 
16213 
16214 
16215 /*
16216  * simple functions implemented as defines
16217  */
16218 
16219 /* In debug mode, the following methods are implemented as function calls to ensure
16220  * type validity.
16221  * In optimized mode, the methods are implemented as defines to improve performance.
16222  * However, we want to have them in the library anyways, so we have to undef the defines.
16223  */
16224 
16225 #undef SCIPboundchgGetNewbound
16226 #undef SCIPboundchgGetVar
16227 #undef SCIPboundchgGetBoundchgtype
16228 #undef SCIPboundchgGetBoundtype
16229 #undef SCIPboundchgIsRedundant
16230 #undef SCIPdomchgGetNBoundchgs
16231 #undef SCIPdomchgGetBoundchg
16232 #undef SCIPholelistGetLeft
16233 #undef SCIPholelistGetRight
16234 #undef SCIPholelistGetNext
16235 #undef SCIPvarGetName
16236 #undef SCIPvarGetNUses
16237 #undef SCIPvarGetData
16238 #undef SCIPvarSetData
16239 #undef SCIPvarSetDelorigData
16240 #undef SCIPvarSetTransData
16241 #undef SCIPvarSetDeltransData
16242 #undef SCIPvarGetStatus
16243 #undef SCIPvarIsOriginal
16244 #undef SCIPvarIsTransformed
16245 #undef SCIPvarIsNegated
16246 #undef SCIPvarGetType
16247 #undef SCIPvarIsBinary
16248 #undef SCIPvarIsIntegral
16249 #undef SCIPvarIsInitial
16250 #undef SCIPvarIsRemovable
16251 #undef SCIPvarIsDeleted
16252 #undef SCIPvarIsDeletable
16253 #undef SCIPvarMarkDeletable
16254 #undef SCIPvarMarkNotDeletable
16255 #undef SCIPvarIsActive
16256 #undef SCIPvarGetIndex
16257 #undef SCIPvarGetProbindex
16258 #undef SCIPvarGetTransVar
16259 #undef SCIPvarGetCol
16260 #undef SCIPvarIsInLP
16261 #undef SCIPvarGetAggrVar
16262 #undef SCIPvarGetAggrScalar
16263 #undef SCIPvarGetAggrConstant
16264 #undef SCIPvarGetMultaggrNVars
16265 #undef SCIPvarGetMultaggrVars
16266 #undef SCIPvarGetMultaggrScalars
16267 #undef SCIPvarGetMultaggrConstant
16268 #undef SCIPvarGetNegatedVar
16269 #undef SCIPvarGetNegationVar
16270 #undef SCIPvarGetNegationConstant
16271 #undef SCIPvarGetObj
16272 #undef SCIPvarGetLbOriginal
16273 #undef SCIPvarGetUbOriginal
16274 #undef SCIPvarGetHolelistOriginal
16275 #undef SCIPvarGetLbGlobal
16276 #undef SCIPvarGetUbGlobal
16277 #undef SCIPvarGetHolelistGlobal
16278 #undef SCIPvarGetBestBoundGlobal
16279 #undef SCIPvarGetWorstBoundGlobal
16280 #undef SCIPvarGetLbLocal
16281 #undef SCIPvarGetUbLocal
16282 #undef SCIPvarGetHolelistLocal
16283 #undef SCIPvarGetBestBoundLocal
16284 #undef SCIPvarGetWorstBoundLocal
16285 #undef SCIPvarGetBestBoundType
16286 #undef SCIPvarGetWorstBoundType
16287 #undef SCIPvarGetLbLazy
16288 #undef SCIPvarGetUbLazy
16289 #undef SCIPvarGetBranchFactor
16290 #undef SCIPvarGetBranchPriority
16291 #undef SCIPvarGetBranchDirection
16292 #undef SCIPvarGetNVlbs
16293 #undef SCIPvarGetVlbVars
16294 #undef SCIPvarGetVlbCoefs
16295 #undef SCIPvarGetVlbConstants
16296 #undef SCIPvarGetNVubs
16297 #undef SCIPvarGetVubVars
16298 #undef SCIPvarGetVubCoefs
16299 #undef SCIPvarGetVubConstants
16300 #undef SCIPvarGetNImpls
16301 #undef SCIPvarGetImplVars
16302 #undef SCIPvarGetImplTypes
16303 #undef SCIPvarGetImplBounds
16304 #undef SCIPvarGetImplIds
16305 #undef SCIPvarGetNCliques
16306 #undef SCIPvarGetCliques
16307 #undef SCIPvarGetLPSol
16308 #undef SCIPvarGetNLPSol
16309 #undef SCIPvarGetBdchgInfoLb
16310 #undef SCIPvarGetNBdchgInfosLb
16311 #undef SCIPvarGetBdchgInfoUb
16312 #undef SCIPvarGetNBdchgInfosUb
16313 #undef SCIPvarGetValuehistory
16314 #undef SCIPvarGetPseudoSol
16315 #undef SCIPvarCatchEvent
16316 #undef SCIPvarDropEvent
16317 #undef SCIPvarGetVSIDS
16318 #undef SCIPbdchgidxGetPos
16319 #undef SCIPbdchgidxIsEarlierNonNull
16320 #undef SCIPbdchgidxIsEarlier
16321 #undef SCIPbdchginfoGetOldbound
16322 #undef SCIPbdchginfoGetNewbound
16323 #undef SCIPbdchginfoGetVar
16324 #undef SCIPbdchginfoGetChgtype
16325 #undef SCIPbdchginfoGetBoundtype
16326 #undef SCIPbdchginfoGetDepth
16327 #undef SCIPbdchginfoGetPos
16328 #undef SCIPbdchginfoGetIdx
16329 #undef SCIPbdchginfoGetInferVar
16330 #undef SCIPbdchginfoGetInferCons
16331 #undef SCIPbdchginfoGetInferProp
16332 #undef SCIPbdchginfoGetInferInfo
16333 #undef SCIPbdchginfoGetInferBoundtype
16334 #undef SCIPbdchginfoIsRedundant
16335 #undef SCIPbdchginfoHasInferenceReason
16336 #undef SCIPbdchginfoIsTighter
16337 
16338 /** returns the new value of the bound in the bound change data */
16340  SCIP_BOUNDCHG* boundchg /**< bound change data */
16341  )
16342 {
16343  assert(boundchg != NULL);
16344 
16345  return boundchg->newbound;
16346 }
16347 
16348 /** returns the variable of the bound change in the bound change data */
16350  SCIP_BOUNDCHG* boundchg /**< bound change data */
16351  )
16352 {
16353  assert(boundchg != NULL);
16354 
16355  return boundchg->var;
16356 }
16357 
16358 /** returns the bound change type of the bound change in the bound change data */
16360  SCIP_BOUNDCHG* boundchg /**< bound change data */
16361  )
16362 {
16363  assert(boundchg != NULL);
16364 
16365  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16366 }
16367 
16368 /** returns the bound type of the bound change in the bound change data */
16370  SCIP_BOUNDCHG* boundchg /**< bound change data */
16371  )
16372 {
16373  assert(boundchg != NULL);
16374 
16375  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16376 }
16377 
16378 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16380  SCIP_BOUNDCHG* boundchg /**< bound change data */
16381  )
16382 {
16383  assert(boundchg != NULL);
16384 
16385  return boundchg->redundant;
16386 }
16387 
16388 /** returns the number of bound changes in the domain change data */
16390  SCIP_DOMCHG* domchg /**< domain change data */
16391  )
16392 {
16393  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16394 }
16395 
16396 /** returns a particular bound change in the domain change data */
16398  SCIP_DOMCHG* domchg, /**< domain change data */
16399  int pos /**< position of the bound change in the domain change data */
16400  )
16401 {
16402  assert(domchg != NULL);
16403  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16404 
16405  return &domchg->domchgbound.boundchgs[pos];
16406 }
16407 
16408 /** returns left bound of open interval in hole */
16410  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16411  )
16412 {
16413  assert(holelist != NULL);
16414 
16415  return holelist->hole.left;
16416 }
16417 
16418 /** returns right bound of open interval in hole */
16420  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16421  )
16422 {
16423  assert(holelist != NULL);
16424 
16425  return holelist->hole.right;
16426 }
16427 
16428 /** returns next hole in list */
16430  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16431  )
16432 {
16433  assert(holelist != NULL);
16434 
16435  return holelist->next;
16436 }
16437 
16438 /** returns the name of the variable
16439  *
16440  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16441  */
16442 const char* SCIPvarGetName(
16443  SCIP_VAR* var /**< problem variable */
16444  )
16445 {
16446  assert(var != NULL);
16447 
16448  return var->name;
16449 }
16450 
16451 /** gets number of times, the variable is currently captured */
16452 int SCIPvarGetNUses(
16453  SCIP_VAR* var /**< problem variable */
16454  )
16455 {
16456  assert(var != NULL);
16457 
16458  return var->nuses;
16459 }
16460 
16461 /** returns the user data of the variable */
16463  SCIP_VAR* var /**< problem variable */
16464  )
16465 {
16466  assert(var != NULL);
16467 
16468  return var->vardata;
16469 }
16470 
16471 /** sets the user data for the variable */
16472 void SCIPvarSetData(
16473  SCIP_VAR* var, /**< problem variable */
16474  SCIP_VARDATA* vardata /**< user variable data */
16475  )
16476 {
16477  assert(var != NULL);
16478 
16479  var->vardata = vardata;
16480 }
16481 
16482 /** sets method to free user data for the original variable */
16484  SCIP_VAR* var, /**< problem variable */
16485  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16486  )
16487 {
16488  assert(var != NULL);
16489  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16490 
16491  var->vardelorig = vardelorig;
16492 }
16493 
16494 /** sets method to transform user data of the variable */
16495 void SCIPvarSetTransData(
16496  SCIP_VAR* var, /**< problem variable */
16497  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16498  )
16499 {
16500  assert(var != NULL);
16501  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16502 
16503  var->vartrans = vartrans;
16504 }
16505 
16506 /** sets method to free transformed user data for the variable */
16508  SCIP_VAR* var, /**< problem variable */
16509  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16510  )
16511 {
16512  assert(var != NULL);
16513 
16514  var->vardeltrans = vardeltrans;
16515 }
16516 
16517 /** sets method to copy this variable into sub-SCIPs */
16518 void SCIPvarSetCopyData(
16519  SCIP_VAR* var, /**< problem variable */
16520  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16521  )
16522 {
16523  assert(var != NULL);
16524 
16525  var->varcopy = varcopy;
16526 }
16527 
16528 /** sets the initial flag of a variable; only possible for original or loose variables */
16530  SCIP_VAR* var, /**< problem variable */
16531  SCIP_Bool initial /**< initial flag */
16532  )
16533 {
16534  assert(var != NULL);
16535 
16537  return SCIP_INVALIDCALL;
16538 
16539  var->initial = initial;
16540 
16541  return SCIP_OKAY;
16542 }
16543 
16544 /** sets the removable flag of a variable; only possible for original or loose variables */
16546  SCIP_VAR* var, /**< problem variable */
16547  SCIP_Bool removable /**< removable flag */
16548  )
16549 {
16550  assert(var != NULL);
16551 
16553  return SCIP_INVALIDCALL;
16554 
16555  var->removable = removable;
16556 
16557  return SCIP_OKAY;
16558 }
16559 
16560 /** gets status of variable */
16562  SCIP_VAR* var /**< problem variable */
16563  )
16564 {
16565  assert(var != NULL);
16566 
16567  return (SCIP_VARSTATUS)(var->varstatus);
16568 }
16569 
16570 /** returns whether the variable belongs to the original problem */
16572  SCIP_VAR* var /**< problem variable */
16573  )
16574 {
16575  assert(var != NULL);
16576  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16577 
16581 }
16582 
16583 /** returns whether the variable belongs to the transformed problem */
16585  SCIP_VAR* var /**< problem variable */
16586  )
16587 {
16588  assert(var != NULL);
16589  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16590 
16594 }
16595 
16596 /** returns whether the variable was created by negation of a different variable */
16598  SCIP_VAR* var /**< problem variable */
16599  )
16600 {
16601  assert(var != NULL);
16602 
16603  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16604 }
16605 
16606 /** gets type of variable */
16608  SCIP_VAR* var /**< problem variable */
16609  )
16610 {
16611  assert(var != NULL);
16612 
16613  return (SCIP_VARTYPE)(var->vartype);
16614 }
16615 
16616 /** returns TRUE if the variable is of binary type; this is the case if:
16617  * (1) variable type is binary
16618  * (2) variable type is integer or implicit integer and
16619  * (i) the lazy lower bound or the global lower bound is greater or equal to zero
16620  * (ii) the lazy upper bound or the global upper bound is less tor equal to one
16621  */
16623  SCIP_VAR* var /**< problem variable */
16624  )
16625 {
16626  assert(var != NULL);
16627 
16628  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16629  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16630 }
16631 
16632 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16634  SCIP_VAR* var /**< problem variable */
16635  )
16636 {
16637  assert(var != NULL);
16638 
16639  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16640 }
16641 
16642 /** returns whether variable's column should be present in the initial root LP */
16644  SCIP_VAR* var /**< problem variable */
16645  )
16646 {
16647  assert(var != NULL);
16648 
16649  return var->initial;
16650 }
16651 
16652 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16654  SCIP_VAR* var /**< problem variable */
16655  )
16656 {
16657  assert(var != NULL);
16658 
16659  return var->removable;
16660 }
16661 
16662 /** returns whether the variable was deleted from the problem */
16664  SCIP_VAR* var /**< problem variable */
16665  )
16666 {
16667  assert(var != NULL);
16668 
16669  return var->deleted;
16670 }
16671 
16672 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16673  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16674  */
16676  SCIP_VAR* var /**< problem variable */
16677  )
16678 {
16679  assert(var != NULL);
16680  assert(var->probindex == -1);
16681 
16682  var->deletable = TRUE;
16683 }
16684 
16685 /** marks the variable to be not deletable from the problem */
16688  )
16689 {
16690  assert(var != NULL);
16691 
16692  var->deletable = FALSE;
16693 }
16694 
16695 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16696  *
16697  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16698  */
16700  SCIP_VAR* var /**< problem variable */
16701  )
16702 {
16703  assert(var != NULL);
16704 
16705  var->delglobalstructs = TRUE;
16706 }
16707 
16708 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16710  SCIP_VAR* var /**< problem variable */
16711  )
16712 {
16713  assert(var != NULL);
16714 
16715  return var->delglobalstructs;
16716 }
16717 
16718 /** returns whether variable is allowed to be deleted completely from the problem */
16721  )
16722 {
16723  assert(var != NULL);
16724 
16725  return var->deletable;
16726 }
16727 
16728 /** returns whether variable is an active (neither fixed nor aggregated) variable */
16730  SCIP_VAR* var /**< problem variable */
16731  )
16732 {
16733  assert(var != NULL);
16734 
16735  return (var->probindex >= 0);
16736 }
16737 
16738 /** gets unique index of variable */
16739 int SCIPvarGetIndex(
16740  SCIP_VAR* var /**< problem variable */
16741  )
16742 {
16743  assert(var != NULL);
16744 
16745  return var->index;
16746 }
16747 
16748 /** gets position of variable in problem, or -1 if variable is not active */
16750  SCIP_VAR* var /**< problem variable */
16751  )
16752 {
16753  assert(var != NULL);
16754 
16755  return var->probindex;
16756 }
16757 
16758 /** gets transformed variable of ORIGINAL variable */
16760  SCIP_VAR* var /**< problem variable */
16761  )
16762 {
16763  assert(var != NULL);
16764  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16765 
16766  return var->data.original.transvar;
16767 }
16768 
16769 /** gets column of COLUMN variable */
16771  SCIP_VAR* var /**< problem variable */
16772  )
16773 {
16774  assert(var != NULL);
16775  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16776 
16777  return var->data.col;
16778 }
16779 
16780 /** returns whether the variable is a COLUMN variable that is member of the current LP */
16782  SCIP_VAR* var /**< problem variable */
16783  )
16784 {
16785  assert(var != NULL);
16786 
16787  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
16788 }
16789 
16790 /** gets aggregation variable y of an aggregated variable x = a*y + c */
16792  SCIP_VAR* var /**< problem variable */
16793  )
16794 {
16795  assert(var != NULL);
16797 
16798  return var->data.aggregate.var;
16799 }
16800 
16801 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
16803  SCIP_VAR* var /**< problem variable */
16804  )
16805 {
16806  assert(var != NULL);
16808 
16809  return var->data.aggregate.scalar;
16810 }
16811 
16812 /** gets aggregation constant c of an aggregated variable x = a*y + c */
16814  SCIP_VAR* var /**< problem variable */
16815  )
16816 {
16817  assert(var != NULL);
16819 
16820  return var->data.aggregate.constant;
16821 }
16822 
16823 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16825  SCIP_VAR* var /**< problem variable */
16826  )
16827 {
16828  assert(var != NULL);
16829  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16830  assert(!var->donotmultaggr);
16831 
16832  return var->data.multaggr.nvars;
16833 }
16834 
16835 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16837  SCIP_VAR* var /**< problem variable */
16838  )
16839 {
16840  assert(var != NULL);
16841  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16842  assert(!var->donotmultaggr);
16843 
16844  return var->data.multaggr.vars;
16845 }
16846 
16847 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16849  SCIP_VAR* var /**< problem variable */
16850  )
16851 {
16852  assert(var != NULL);
16853  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16854  assert(!var->donotmultaggr);
16855 
16856  return var->data.multaggr.scalars;
16857 }
16858 
16859 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16861  SCIP_VAR* var /**< problem variable */
16862  )
16863 {
16864  assert(var != NULL);
16865  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16866  assert(!var->donotmultaggr);
16867 
16868  return var->data.multaggr.constant;
16869 }
16870 
16871 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
16873  SCIP_VAR* var /**< negated problem variable */
16874  )
16875 {
16876  assert(var != NULL);
16877 
16878  return var->negatedvar;
16879 }
16880 
16881 /** gets the negation variable x of a negated variable x' = offset - x */
16883  SCIP_VAR* var /**< negated problem variable */
16884  )
16885 {
16886  assert(var != NULL);
16887  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16888 
16889  return var->negatedvar;
16890 }
16891 
16892 /** gets the negation offset of a negated variable x' = offset - x */
16894  SCIP_VAR* var /**< negated problem variable */
16895  )
16896 {
16897  assert(var != NULL);
16898  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16899 
16900  return var->data.negate.constant;
16901 }
16902 
16903 /** gets objective function value of variable */
16905  SCIP_VAR* var /**< problem variable */
16906  )
16907 {
16908  assert(var != NULL);
16909 
16910  return var->obj;
16911 }
16912 
16913 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
16915  SCIP_VAR* var /**< problem variable */
16916  )
16917 {
16918  assert(var != NULL);
16919 
16920  return var->unchangedobj;
16921 }
16922 
16923 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
16924  * e.g. obj(x) = 1 this method returns for ~x the value -1
16925  */
16927  SCIP_VAR* var, /**< problem variable */
16928  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
16929  )
16930 {
16931  SCIP_VAR* probvar = var;
16932  SCIP_Real mult = 1.0;
16933 
16934  assert(probvar != NULL);
16935  assert(aggrobj != NULL);
16936 
16937  while( probvar != NULL )
16938  {
16939  switch( SCIPvarGetStatus(probvar) )
16940  {
16942  case SCIP_VARSTATUS_LOOSE:
16943  case SCIP_VARSTATUS_COLUMN:
16944  (*aggrobj) = mult * SCIPvarGetObj(probvar);
16945  return SCIP_OKAY;
16946 
16947  case SCIP_VARSTATUS_FIXED:
16948  assert(SCIPvarGetObj(probvar) == 0.0);
16949  (*aggrobj) = 0.0;
16950  return SCIP_OKAY;
16951 
16953  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16954  if ( probvar->data.multaggr.nvars == 1 )
16955  {
16956  assert( probvar->data.multaggr.vars != NULL );
16957  assert( probvar->data.multaggr.scalars != NULL );
16958  assert( probvar->data.multaggr.vars[0] != NULL );
16959  mult *= probvar->data.multaggr.scalars[0];
16960  probvar = probvar->data.multaggr.vars[0];
16961  break;
16962  }
16963  else
16964  {
16965  SCIP_Real tmpobj;
16966  int v;
16967 
16968  (*aggrobj) = 0.0;
16969 
16970  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
16971  {
16972  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
16973  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
16974  }
16975  return SCIP_OKAY;
16976  }
16977 
16978  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
16979  assert(probvar->data.aggregate.var != NULL);
16980  mult *= probvar->data.aggregate.scalar;
16981  probvar = probvar->data.aggregate.var;
16982  break;
16983 
16984  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
16985  assert(probvar->negatedvar != NULL);
16986  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
16987  assert(probvar->negatedvar->negatedvar == probvar);
16988  mult *= -1.0;
16989  probvar = probvar->negatedvar;
16990  break;
16991 
16992  default:
16993  SCIPABORT();
16994  return SCIP_INVALIDDATA; /*lint !e527*/
16995  }
16996  }
16997 
16998  return SCIP_INVALIDDATA;
16999 }
17000 
17001 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17003  SCIP_VAR* var /**< original problem variable */
17004  )
17005 {
17006  assert(var != NULL);
17007  assert(SCIPvarIsOriginal(var));
17008 
17010  return var->data.original.origdom.lb;
17011  else
17012  {
17013  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17014  assert(var->negatedvar != NULL);
17016 
17017  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17018  }
17019 }
17020 
17021 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17023  SCIP_VAR* var /**< original problem variable */
17024  )
17025 {
17026  assert(var != NULL);
17027  assert(SCIPvarIsOriginal(var));
17028 
17030  return var->data.original.origdom.ub;
17031  else
17032  {
17033  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17034  assert(var->negatedvar != NULL);
17036 
17037  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17038  }
17039 }
17040 
17041 /** gets the original hole list of an original variable */
17043  SCIP_VAR* var /**< problem variable */
17044  )
17045 {
17046  assert(var != NULL);
17047  assert(SCIPvarIsOriginal(var));
17048 
17050  return var->data.original.origdom.holelist;
17051 
17052  return NULL;
17053 }
17054 
17055 /** gets global lower bound of variable */
17057  SCIP_VAR* var /**< problem variable */
17058  )
17059 {
17060  assert(var != NULL);
17061 
17062  return var->glbdom.lb;
17063 }
17064 
17065 /** gets global upper bound of variable */
17067  SCIP_VAR* var /**< problem variable */
17068  )
17069 {
17070  assert(var != NULL);
17071 
17072  return var->glbdom.ub;
17073 }
17074 
17075 /** gets the global hole list of an active variable */
17077  SCIP_VAR* var /**< problem variable */
17078  )
17079 {
17080  assert(var != NULL);
17081 
17082  return var->glbdom.holelist;
17083 }
17084 
17085 /** gets best global bound of variable with respect to the objective function */
17087  SCIP_VAR* var /**< problem variable */
17088  )
17089 {
17090  assert(var != NULL);
17091 
17092  if( var->obj >= 0.0 )
17093  return var->glbdom.lb;
17094  else
17095  return var->glbdom.ub;
17096 }
17097 
17098 /** gets worst global bound of variable with respect to the objective function */
17100  SCIP_VAR* var /**< problem variable */
17101  )
17102 {
17103  assert(var != NULL);
17104 
17105  if( var->obj >= 0.0 )
17106  return var->glbdom.ub;
17107  else
17108  return var->glbdom.lb;
17109 }
17110 
17111 /** gets current lower bound of variable */
17113  SCIP_VAR* var /**< problem variable */
17114  )
17115 {
17116  assert(var != NULL);
17117 
17118  return var->locdom.lb;
17119 }
17120 
17121 /** gets current upper bound of variable */
17123  SCIP_VAR* var /**< problem variable */
17124  )
17125 {
17126  assert(var != NULL);
17127 
17128  return var->locdom.ub;
17129 }
17130 
17131 /** gets the current hole list of an active variable */
17133  SCIP_VAR* var /**< problem variable */
17134  )
17135 {
17136  assert(var != NULL);
17137 
17138  return var->locdom.holelist;
17139 }
17140 
17141 /** gets best local bound of variable with respect to the objective function */
17143  SCIP_VAR* var /**< problem variable */
17144  )
17145 {
17146  assert(var != NULL);
17147 
17148  if( var->obj >= 0.0 )
17149  return var->locdom.lb;
17150  else
17151  return var->locdom.ub;
17152 }
17153 
17154 /** gets worst local bound of variable with respect to the objective function */
17156  SCIP_VAR* var /**< problem variable */
17157  )
17158 {
17159  assert(var != NULL);
17160 
17161  if( var->obj >= 0.0 )
17162  return var->locdom.ub;
17163  else
17164  return var->locdom.lb;
17165 }
17166 
17167 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17169  SCIP_VAR* var /**< problem variable */
17170  )
17171 {
17172  assert(var != NULL);
17173 
17174  if( var->obj >= 0.0 )
17175  return SCIP_BOUNDTYPE_LOWER;
17176  else
17177  return SCIP_BOUNDTYPE_UPPER;
17178 }
17179 
17180 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17182  SCIP_VAR* var /**< problem variable */
17183  )
17184 {
17185  assert(var != NULL);
17186 
17187  if( var->obj >= 0.0 )
17188  return SCIP_BOUNDTYPE_UPPER;
17189  else
17190  return SCIP_BOUNDTYPE_LOWER;
17191 }
17192 
17193 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17195  SCIP_VAR* var /**< problem variable */
17196  )
17197 {
17198  assert(var != NULL);
17199 
17200  return var->lazylb;
17201 }
17202 
17203 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17205  SCIP_VAR* var /**< problem variable */
17206  )
17207 {
17208  assert(var != NULL);
17209 
17210  return var->lazyub;
17211 }
17212 
17213 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17214  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17215  */
17217  SCIP_VAR* var /**< problem variable */
17218  )
17219 {
17220  assert(var != NULL);
17221 
17222  return var->branchfactor;
17223 }
17224 
17225 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17226  * with lower priority
17227  */
17229  SCIP_VAR* var /**< problem variable */
17230  )
17231 {
17232  assert(var != NULL);
17233 
17234  return var->branchpriority;
17235 }
17236 
17237 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17239  SCIP_VAR* var /**< problem variable */
17240  )
17241 {
17242  assert(var != NULL);
17243 
17244  return (SCIP_BRANCHDIR)var->branchdirection;
17245 }
17246 
17247 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17248 int SCIPvarGetNVlbs(
17249  SCIP_VAR* var /**< problem variable */
17250  )
17251 {
17252  assert(var != NULL);
17253 
17254  return SCIPvboundsGetNVbds(var->vlbs);
17255 }
17256 
17257 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17258  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17259  */
17261  SCIP_VAR* var /**< problem variable */
17262  )
17263 {
17264  assert(var != NULL);
17265 
17266  return SCIPvboundsGetVars(var->vlbs);
17267 }
17268 
17269 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17271  SCIP_VAR* var /**< problem variable */
17272  )
17273 {
17274  assert(var != NULL);
17275 
17276  return SCIPvboundsGetCoefs(var->vlbs);
17277 }
17278 
17279 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17281  SCIP_VAR* var /**< problem variable */
17282  )
17283 {
17284  assert(var != NULL);
17285 
17286  return SCIPvboundsGetConstants(var->vlbs);
17287 }
17288 
17289 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17290 int SCIPvarGetNVubs(
17291  SCIP_VAR* var /**< problem variable */
17292  )
17293 {
17294  assert(var != NULL);
17295 
17296  return SCIPvboundsGetNVbds(var->vubs);
17297 }
17298 
17299 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17300  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17301  */
17303  SCIP_VAR* var /**< problem variable */
17304  )
17305 {
17306  assert(var != NULL);
17307 
17308  return SCIPvboundsGetVars(var->vubs);
17309 }
17310 
17311 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17313  SCIP_VAR* var /**< problem variable */
17314  )
17315 {
17316  assert(var != NULL);
17317 
17318  return SCIPvboundsGetCoefs(var->vubs);
17319 }
17320 
17321 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17323  SCIP_VAR* var /**< problem variable */
17324  )
17325 {
17326  assert(var != NULL);
17327 
17328  return SCIPvboundsGetConstants(var->vubs);
17329 }
17330 
17331 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17332  * there are no implications for nonbinary variable x
17333  */
17334 int SCIPvarGetNImpls(
17335  SCIP_VAR* var, /**< active problem variable */
17336  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17337  )
17338 {
17339  assert(var != NULL);
17340  assert(SCIPvarIsActive(var));
17341 
17342  return SCIPimplicsGetNImpls(var->implics, varfixing);
17343 }
17344 
17345 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17346  * problem variable x, there are no implications for nonbinary variable x;
17347  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17348  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17349  * (see SCIPvarGetIndex())
17350  */
17352  SCIP_VAR* var, /**< active problem variable */
17353  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17354  )
17355 {
17356  assert(var != NULL);
17357  assert(SCIPvarIsActive(var));
17358 
17359  return SCIPimplicsGetVars(var->implics, varfixing);
17360 }
17361 
17362 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17363  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17364  * there are no implications for nonbinary variable x
17365  */
17367  SCIP_VAR* var, /**< active problem variable */
17368  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17369  )
17370 {
17371  assert(var != NULL);
17372  assert(SCIPvarIsActive(var));
17373 
17374  return SCIPimplicsGetTypes(var->implics, varfixing);
17375 }
17376 
17377 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17378  * variable x, there are no implications for nonbinary variable x
17379  */
17381  SCIP_VAR* var, /**< active problem variable */
17382  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17383  )
17384 {
17385  assert(var != NULL);
17386  assert(SCIPvarIsActive(var));
17387 
17388  return SCIPimplicsGetBounds(var->implics, varfixing);
17389 }
17390 
17391 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17392  * there are no implications for nonbinary variable x.
17393  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17394  * its id is negative, otherwise it is nonnegative.
17395  */
17396 int* SCIPvarGetImplIds(
17397  SCIP_VAR* var, /**< active problem variable */
17398  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17399  )
17400 {
17401  assert(var != NULL);
17402  assert(SCIPvarIsActive(var));
17403 
17404  return SCIPimplicsGetIds(var->implics, varfixing);
17405 }
17406 
17407 /** gets number of cliques, the active variable is contained in */
17408 int SCIPvarGetNCliques(
17409  SCIP_VAR* var, /**< active problem variable */
17410  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17411  )
17412 {
17413  assert(var != NULL);
17414 
17415  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17416 }
17417 
17418 /** gets array of cliques, the active variable is contained in */
17420  SCIP_VAR* var, /**< active problem variable */
17421  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17422  )
17423 {
17424  assert(var != NULL);
17425 
17426  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17427 }
17428 
17429 /** gets primal LP solution value of variable */
17431  SCIP_VAR* var /**< problem variable */
17432  )
17433 {
17434  assert(var != NULL);
17435 
17437  return SCIPcolGetPrimsol(var->data.col);
17438  else
17439  return SCIPvarGetLPSol_rec(var);
17440 }
17441 
17442 /** gets primal NLP solution value of variable */
17444  SCIP_VAR* var /**< problem variable */
17445  )
17446 {
17447  assert(var != NULL);
17448 
17450  return var->nlpsol;
17451  else
17452  return SCIPvarGetNLPSol_rec(var);
17453 }
17454 
17455 /** return lower bound change info at requested position */
17457  SCIP_VAR* var, /**< problem variable */
17458  int pos /**< requested position */
17459  )
17460 {
17461  assert(pos >= 0);
17462  assert(pos < var->nlbchginfos);
17463 
17464  return &var->lbchginfos[pos];
17465 }
17466 
17467 /** gets the number of lower bound change info array */
17469  SCIP_VAR* var /**< problem variable */
17470  )
17471 {
17472  return var->nlbchginfos;
17473 }
17474 
17475 /** return upper bound change info at requested position */
17477  SCIP_VAR* var, /**< problem variable */
17478  int pos /**< requested position */
17479  )
17480 {
17481  assert(pos >= 0);
17482  assert(pos < var->nubchginfos);
17483 
17484  return &var->ubchginfos[pos];
17485 }
17486 
17487 /** gets the number upper bound change info array */
17489  SCIP_VAR* var /**< problem variable */
17490  )
17491 {
17492  assert(var != NULL);
17493 
17494  return var->nubchginfos;
17495 }
17496 
17497 /** returns the value based history for the variable */
17499  SCIP_VAR* var /**< problem variable */
17500  )
17501 {
17502  assert(var != NULL);
17503 
17504  return var->valuehistory;
17505 }
17506 
17507 /** gets pseudo solution value of variable */
17509  SCIP_VAR* var /**< problem variable */
17510  )
17511 {
17512  assert(var != NULL);
17513 
17515  return SCIPvarGetBestBoundLocal(var);
17516  else
17517  return SCIPvarGetPseudoSol_rec(var);
17518 }
17519 
17520 /** returns the variable's VSIDS score */
17522  SCIP_VAR* var, /**< problem variable */
17523  SCIP_STAT* stat, /**< problem statistics */
17524  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17525  )
17526 {
17527  assert(var != NULL);
17528 
17530  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17531  else
17532  return SCIPvarGetVSIDS_rec(var, stat, dir);
17533 }
17534 
17535 /** includes event handler with given data in variable's event filter */
17537  SCIP_VAR* var, /**< problem variable */
17538  BMS_BLKMEM* blkmem, /**< block memory */
17539  SCIP_SET* set, /**< global SCIP settings */
17540  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17541  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17542  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17543  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17544  )
17545 {
17546  assert(var != NULL);
17547  assert(set != NULL);
17548  assert(var->scip == set->scip);
17549  assert(var->eventfilter != NULL);
17550  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17551  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17552  assert(SCIPvarIsTransformed(var));
17553 
17554  SCIPdebugMessage("catch event of type 0x%x of variable <%s> with handler %p and data %p\n",
17555  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17556 
17557  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17558 
17559  return SCIP_OKAY;
17560 }
17561 
17562 /** deletes event handler with given data from variable's event filter */
17564  SCIP_VAR* var, /**< problem variable */
17565  BMS_BLKMEM* blkmem, /**< block memory */
17566  SCIP_SET* set, /**< global SCIP settings */
17567  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17568  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17569  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17570  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17571  )
17572 {
17573  assert(var != NULL);
17574  assert(set != NULL);
17575  assert(var->scip == set->scip);
17576  assert(var->eventfilter != NULL);
17577  assert(SCIPvarIsTransformed(var));
17578 
17579  SCIPdebugMessage("drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr, (void*)eventdata);
17580 
17581  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17582 
17583  return SCIP_OKAY;
17584 }
17585 
17586 /** returns the position of the bound change index */
17587 int SCIPbdchgidxGetPos(
17588  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17589  )
17590 {
17591  assert(bdchgidx != NULL);
17592 
17593  return bdchgidx->pos;
17594 }
17595 
17596 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17598  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17599  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17600  )
17601 {
17602  assert(bdchgidx1 != NULL);
17603  assert(bdchgidx1->depth >= -2);
17604  assert(bdchgidx1->pos >= 0);
17605  assert(bdchgidx2 != NULL);
17606  assert(bdchgidx2->depth >= -2);
17607  assert(bdchgidx2->pos >= 0);
17608 
17609  return (bdchgidx1->depth < bdchgidx2->depth)
17610  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17611 }
17612 
17613 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17614  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17615  * last bound change was applied to the current node
17616  */
17618  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17619  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17620  )
17621 {
17622  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17623  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17624  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17625  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17626 
17627  if( bdchgidx1 == NULL )
17628  return FALSE;
17629  else if( bdchgidx2 == NULL )
17630  return TRUE;
17631  else
17632  return (bdchgidx1->depth < bdchgidx2->depth)
17633  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17634 }
17635 
17636 /** returns old bound that was overwritten for given bound change information */
17638  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17639  )
17640 {
17641  assert(bdchginfo != NULL);
17642 
17643  return bdchginfo->oldbound;
17644 }
17645 
17646 /** returns new bound installed for given bound change information */
17648  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17649  )
17650 {
17651  assert(bdchginfo != NULL);
17652 
17653  return bdchginfo->newbound;
17654 }
17655 
17656 /** returns variable that belongs to the given bound change information */
17658  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17659  )
17660 {
17661  assert(bdchginfo != NULL);
17662 
17663  return bdchginfo->var;
17664 }
17665 
17666 /** returns whether the bound change information belongs to a branching decision or a deduction */
17668  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17669  )
17670 {
17671  assert(bdchginfo != NULL);
17672 
17673  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17674 }
17675 
17676 /** returns whether the bound change information belongs to a lower or upper bound change */
17678  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17679  )
17680 {
17681  assert(bdchginfo != NULL);
17682 
17683  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17684 }
17685 
17686 /** returns depth level of given bound change information */
17688  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17689  )
17690 {
17691  assert(bdchginfo != NULL);
17692 
17693  return bdchginfo->bdchgidx.depth;
17694 }
17695 
17696 /** returns bound change position in its depth level of given bound change information */
17698  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17699  )
17700 {
17701  assert(bdchginfo != NULL);
17702 
17703  return bdchginfo->bdchgidx.pos;
17704 }
17705 
17706 /** returns bound change index of given bound change information */
17708  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17709  )
17710 {
17711  assert(bdchginfo != NULL);
17712 
17713  return &bdchginfo->bdchgidx;
17714 }
17715 
17716 /** returns inference variable of given bound change information */
17718  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17719  )
17720 {
17721  assert(bdchginfo != NULL);
17724 
17725  return bdchginfo->inferencedata.var;
17726 }
17727 
17728 /** returns inference constraint of given bound change information */
17730  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17731  )
17732 {
17733  assert(bdchginfo != NULL);
17735  assert(bdchginfo->inferencedata.reason.cons != NULL);
17736 
17737  return bdchginfo->inferencedata.reason.cons;
17738 }
17739 
17740 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
17742  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17743  )
17744 {
17745  assert(bdchginfo != NULL);
17747 
17748  return bdchginfo->inferencedata.reason.prop;
17749 }
17750 
17751 /** returns inference user information of given bound change information */
17753  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17754  )
17755 {
17756  assert(bdchginfo != NULL);
17759 
17760  return bdchginfo->inferencedata.info;
17761 }
17762 
17763 /** returns inference bound of inference variable of given bound change information */
17765  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17766  )
17767 {
17768  assert(bdchginfo != NULL);
17771 
17772  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
17773 }
17774 
17775 /** returns the relaxed bound change type */
17777  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
17778  )
17779 {
17780  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
17781 }
17782 
17783 
17784 /** returns whether the bound change information belongs to a redundant bound change */
17786  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17787  )
17788 {
17789  assert(bdchginfo != NULL);
17790  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
17791 
17792  return bdchginfo->redundant;
17793 }
17794 
17795 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
17797  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17798  )
17799 {
17800  assert(bdchginfo != NULL);
17801 
17804  && bdchginfo->inferencedata.reason.prop != NULL);
17805 }
17806 
17807 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
17808  * has a tighter new bound as the second bound change
17809  */
17811  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
17812  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
17813  )
17814 {
17815  assert(bdchginfo1 != NULL);
17816  assert(bdchginfo2 != NULL);
17817  assert(bdchginfo1->var == bdchginfo2->var);
17818  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
17819 
17820  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
17821  ? bdchginfo1->newbound > bdchginfo2->newbound
17822  : bdchginfo1->newbound < bdchginfo2->newbound);
17823 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:555
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16644
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16598
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16360
SCIP_HOLELIST * holelist
Definition: struct_var.h:161
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1650
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17777
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1667
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1515
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14608
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5180
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:406
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:422
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17217
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13376
internal methods for managing events
static SCIP_RETCODE boundchgReleaseData(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:927
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17431
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:8865
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11206
SCIP_RETCODE SCIPvarIncInferenceSum(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14735
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:85
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:568
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3111
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16792
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5238
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5688
internal methods for storing primal CIP solutions
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17688
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:487
SCIP_RETCODE SCIPvarIncVSIDS(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14255
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8747
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16430
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9858
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12537
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17123
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13260
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:19403
int nubchginfos
Definition: struct_var.h:261
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:5837
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17648
internal methods for branch and bound tree
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:110
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:600
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15508
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:228
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16390
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16350
unsigned int inferboundtype
Definition: struct_var.h:91
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16861
char * name
Definition: struct_var.h:227
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16463
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17730
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:965
unsigned int boundchgtype
Definition: struct_var.h:112
union SCIP_BoundChg::@11 data
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition: implics.c:1135
SCIP_HOLE hole
Definition: struct_var.h:49
SCIP_Real bestrootsol
Definition: struct_var.h:205
char * name
Definition: struct_lp.h:214
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5367
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17742
static SCIP_RETCODE varProcessChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6332
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5578
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1790
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:127
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6680
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:84
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5455
SCIP_RETCODE SCIPvarCreateTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:2039
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13849
methods for implications, variable bounds, and cliques
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4399
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2057
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1446
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:13984
#define SCIP_MAXSTRLEN
Definition: def.h:201
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17261
SCIP_DOM origdom
Definition: struct_var.h:167
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1788
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13036
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16664
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:724
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3062
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6064
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16443
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:123
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:584
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5303
SCIP_Real lastbranchvalue
Definition: struct_stat.h:107
#define NULL
Definition: lpi_spx.cpp:130
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1035
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:258
#define MAXABSVBCOEF
Definition: var.c:66
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15562
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1808
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15220
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:6964
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16021
SCIP_Real constant
Definition: struct_var.h:182
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int addnlocksdown, int addnlocksup)
Definition: var.c:3034
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1139
SCIP_Real bestrootredcost
Definition: struct_var.h:206
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8049
SCIP_HISTORY * historycrun
Definition: struct_var.h:243
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:140
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3163
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1383
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6123
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11573
SCIP_Longint closestvblpcount
Definition: struct_var.h:245
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8357
SCIP_RETCODE SCIPvarParseOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2391
static SCIP_RETCODE varEventGholeAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right)
Definition: var.c:6259
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3029
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5042
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15036
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:152
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17023
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17335
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:18748
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3504
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17409
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2183
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:241
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:18596
static SCIP_RETCODE boundchgApplyGlobal(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:835
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5678
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14341
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12191
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:124
unsigned int nboundchgs
Definition: struct_var.h:121
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17708
SCIP_RETCODE SCIPvarCatchEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: var.c:17537
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3086
SCIP_HOLELIST * newlist
Definition: struct_var.h:57
SCIP_Real right
Definition: struct_var.h:43
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:314
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5598
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:40
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4208
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17229
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17718
#define FALSE
Definition: def.h:56
int lppos
Definition: struct_lp.h:160
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:19393
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5721
static SCIP_RETCODE varAddUbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:478
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:96
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1274
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17323
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17291
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17753
SCIP_RETCODE SCIPboundchgUndo(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:750
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3277
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15418
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:67
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16530
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3013
SCIP_Real constant
Definition: struct_var.h:192
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:8174
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5292
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16410
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:281
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14227
#define TRUE
Definition: def.h:55
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5579
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17618
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14564
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:109
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15375
SCIP_HOLELIST * oldlist
Definition: struct_var.h:58
#define MAXIMPLSCLOSURE
Definition: var.c:63
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:610
#define SCIP_CALL(x)
Definition: def.h:266
int nlbchginfos
Definition: struct_var.h:259
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16018
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2838
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
SCIP_RETCODE SCIPvarCreateOriginal(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_DECL_VARCOPY((*varcopy)), SCIP_VARDATA *vardata)
Definition: var.c:1996
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16825
SCIP_RETCODE SCIPvarAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10214
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:170
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7732
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5613
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4766
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:53
SCIP_RETCODE SCIPvarChgBdLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7706
SCIP_Real SCIPvarGetRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12670
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2797
SCIP_RETCODE SCIPvarChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6823
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition: var.c:1859
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:837
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15263
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17067
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:513
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10537
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16508
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1493
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11270
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12514
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17588
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3172
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17249
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10742
int index
Definition: struct_var.h:246
SCIP_Real constant
Definition: struct_var.h:175
unsigned int domchgtype
Definition: struct_var.h:140
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5314
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1466
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16073
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13630
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6014
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1176
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:257
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17133
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16814
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11083
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:668
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12400
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12607
SCIP_HOLECHG * holechgs
Definition: struct_var.h:132
SCIP_Real obj
Definition: struct_var.h:201
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14948
SCIP_RETCODE SCIProwIncCoef(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_COL *col, SCIP_Real incval)
Definition: lp.c:5294
SCIP_Real relaxsol
Definition: struct_var.h:208
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1536
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:895
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5378
int conflictlbcount
Definition: struct_var.h:262
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13249
internal methods for LP management
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16873
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:423
SCIP_VAR ** vars
Definition: struct_var.h:184
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:190
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11198
internal methods for branching and inference history
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17598
int nrootintfixings
Definition: struct_stat.h:171
int branchpriority
Definition: struct_var.h:257
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16496
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:515
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1245
static SCIP_RETCODE varParse(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, const char *str, char *name, SCIP_Real *lb, SCIP_Real *ub, SCIP_Real *obj, SCIP_VARTYPE *vartype, SCIP_Real *lazylb, SCIP_Real *lazyub, SCIP_Bool local, char **endptr, SCIP_Bool *success)
Definition: var.c:2252
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17381
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16146
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:199
#define EPSISINT(x, eps)
Definition: def.h:164
SCIP_VAR * var
Definition: struct_var.h:176
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:95
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12261
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17509
int nrootboundchgs
Definition: struct_stat.h:169
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:140
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5274
static SCIP_RETCODE varEventLbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7041
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:135
internal methods for propagators
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2159
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15130
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16740
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17444
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:501
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:7215
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1425
SCIP_Real conflictrelaxedub
Definition: struct_var.h:214
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16720
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16883
unsigned int inferboundtype
Definition: struct_var.h:114
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:472
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17352
SCIP_RETCODE SCIPvarChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7455
union SCIP_Var::@12 data
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5220
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12145
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:269
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, SCIP_VARTYPE vartype)
Definition: var.c:5713
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18674
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17239
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10763
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:437
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:12723
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17271
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17169
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:16915
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:247
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:213
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10953
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13708
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16634
SCIP_AGGREGATE aggregate
Definition: struct_var.h:223
SCIP_Real lazylb
Definition: struct_var.h:215
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:416
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16750
static SCIP_RETCODE varEventUbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:7079
SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:1309
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1715
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:6987
static SCIP_RETCODE varProcessChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7294
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4191
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:16927
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:526
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3071
internal methods for storing and manipulating the main problem
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15859
#define MAX_CLIQUELENGTH
Definition: var.c:12719
#define SCIPerrorMessage
Definition: pub_message.h:45
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16676
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:16283
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1269
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1087
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:235
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15981
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:986
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:16015
SCIP_Bool SCIPvarPscostThresholdProbabilityTest(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_Real frac, SCIP_Real threshold, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14131
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:376
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:917
SCIP_Longint lpcount
Definition: struct_stat.h:141
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18639
SCIP_RETCODE SCIPimplicsAdd(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *conflict, SCIP_Bool *added)
Definition: implics.c:630
SCIP_RETCODE SCIPvarChgObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PROB *prob, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newobj)
Definition: var.c:5764
int lbchginfossize
Definition: struct_var.h:258
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11541
unsigned int varstatus
Definition: struct_var.h:272
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2752
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:681
SCIP_Real bestrootlpobjval
Definition: struct_var.h:207
SCIP_VARDATA * vardata
Definition: struct_var.h:232
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:5951
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17489
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13757
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16473
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:210
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:8275
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12120
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7620
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3358
SCIP_HOLECHG * holechgs
Definition: struct_var.h:142
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17469
static SCIP_RETCODE varProcessChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6507
unsigned int pos
Definition: struct_var.h:111
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1827
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4691
SCIP_VAR * transvar
Definition: struct_var.h:168
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:153
#define MAXDNOM
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16803
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5758
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:96
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:411
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1792
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:542
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:584
unsigned int initial
Definition: struct_var.h:266
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15175
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13451
SCIP_NEGATE negate
Definition: struct_var.h:225
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11263
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4133
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:74
static SCIP_RETCODE varProcessChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7132
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13116
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:134
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3037
int nparentvars
Definition: struct_var.h:253
SCIP_Real unchangedobj
Definition: struct_var.h:202
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3559
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9484
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14472
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
internal methods for global SCIP settings
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:13946
SCIP_VBOUNDS * vubs
Definition: struct_var.h:236
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5666
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14903
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17678
SCIP_RETCODE SCIPvarIncNBranchings(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, int depth)
Definition: var.c:14651
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2219
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13804
static SCIP_RETCODE varAddTransitiveBinaryClosureImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9203
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5406
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3045
int closestvubidx
Definition: struct_var.h:265
internal methods for relaxators
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:461
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:16519
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5202
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10897
SCIP_Real vsidsweight
Definition: struct_stat.h:96
SCIP_RETCODE SCIPvarChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7581
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:253
unsigned int nboundchgs
Definition: struct_var.h:139
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16837
unsigned int eventmask
Definition: struct_event.h:179
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11168
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14519
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17420
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2873
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15606
unsigned int branchdirection
Definition: struct_var.h:274
int ubchginfossize
Definition: struct_var.h:260
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1589
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5622
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17143
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:254
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:96
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:326
int var_probindex
Definition: struct_lp.h:166
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17195
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6048
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:12970
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:16453
static SCIP_RETCODE varEventObjChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldobj, SCIP_Real newobj)
Definition: var.c:5737
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10827
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4914
#define SCIP_UNKNOWN
Definition: def.h:148
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5325
unsigned int vartype
Definition: struct_var.h:271
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
unsigned int boundchgtype
Definition: struct_var.h:89
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:423
SCIP_RETCODE SCIPvarIncCutoffSum(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real weight)
Definition: var.c:14819
static SCIP_RETCODE varEventGlbChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6183
SCIP_VAR * var
Definition: struct_var.h:88
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:86
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3149
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13070
static SCIP_RETCODE varProcessAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8476
#define SCIP_Bool
Definition: def.h:53
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15662
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17043
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2740
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:410
SCIP_Real ub
Definition: struct_var.h:160
unsigned int boundtype
Definition: struct_var.h:90
unsigned int deletable
Definition: struct_var.h:268
#define EPSZ(x, eps)
Definition: def.h:157
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5631
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:5857
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12526
SCIP_Bool divingobjchg
Definition: struct_lp.h:350
SCIP_MULTAGGR multaggr
Definition: struct_var.h:224
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7822
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17477
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:538
unsigned int deleted
Definition: struct_var.h:269
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3092
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3563
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:8245
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3053
SCIP_RETCODE SCIPboundchgApply(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, int pos, SCIP_Bool *cutoff)
Definition: var.c:553
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3123
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17765
unsigned int removable
Definition: struct_var.h:267
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17303
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2538
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8115
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16760
unsigned int redundant
Definition: struct_var.h:93
SCIP_Real oldbound
Definition: struct_var.h:106
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:419
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10660
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16782
int closestvlbidx
Definition: struct_var.h:264
int nuses
Definition: struct_var.h:254
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15320
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12328
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16484
SCIP_RETCODE SCIPvarFixBinary(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10446
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:111
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10699
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16398
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:59
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17077
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:159
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15718
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18606
int probindex
Definition: struct_var.h:247
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8228
SCIP_RETCODE SCIPvarCopy(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP *sourcescip, SCIP_VAR *sourcevar, SCIP_HASHMAP *varmap, SCIP_HASHMAP *consmap, SCIP_Bool global)
Definition: var.c:2081
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13177
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:616
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15998
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11481
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5600
SCIP_RETCODE SCIPcliquetableAdd(SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: implics.c:2240
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1495
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3267
SCIP_RETCODE SCIPvarIncNActiveConflicts(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_BRANCHDIR dir, SCIP_Real value, SCIP_Real length)
Definition: var.c:14391
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition: var.c:8995
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:38140
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3608
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3183
SCIP * scip
Definition: struct_var.h:199
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:239
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12448
int nlocksup
Definition: struct_var.h:256
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2118
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17786
int conflictubcount
Definition: struct_var.h:263
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3021
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2180
SCIP_DOM locdom
Definition: struct_var.h:218
static SCIP_RETCODE varAddTransitiveImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9276
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17367
#define SCIP_REAL_MAX
Definition: def.h:128
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5912
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:244
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2810
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:402
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11249
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16654
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:107
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16905
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:655
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:16894
SCIP_RETCODE SCIPvarAddToRow(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: var.c:13523
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3423
SCIP_Real newbound
Definition: struct_var.h:82
#define SCIP_REAL_MIN
Definition: def.h:129
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3464
SCIP_VAR ** parentvars
Definition: struct_var.h:233
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:414
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2566
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5747
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16771
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:151
SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7013
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16623
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17658
#define SCIP_DEFAULT_INFINITY
Definition: def.h:132
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1201
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:94
SCIP_HOLELIST * next
Definition: struct_var.h:50
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:5845
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17205
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:629
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:407
unsigned int boundtype
Definition: struct_var.h:113
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11255
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:662
static const SCIP_Real scalars[]
Definition: lp.c:5506
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5063
int lpipos
Definition: struct_lp.h:161
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8017
#define REALABS(x)
Definition: def.h:151
SCIP_Longint domchgcount
Definition: struct_stat.h:85
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16370
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3389
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:1978
SCIP_Real lazyub
Definition: struct_var.h:216
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1675
unsigned int redundant
Definition: struct_var.h:115
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:42
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: var.c:3729
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:184
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16608
SCIP_Bool SCIPvarSignificantPscostDifference(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *varx, SCIP_Real fracx, SCIP_VAR *vary, SCIP_Real fracy, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool onesided)
Definition: var.c:14064
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1802
SCIP_VAR * var
Definition: struct_var.h:108
public methods for message output
int nrootboundchgsrun
Definition: struct_stat.h:170
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3181
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:602
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17797
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13316
static SCIP_RETCODE varAddVbound(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_BOUNDTYPE vbtype, SCIP_VAR *vbvar, SCIP_Real vbcoef, SCIP_Real vbconstant)
Definition: var.c:8767
SCIP_Real * scalars
Definition: struct_var.h:183
SCIP_IMPLICS * implics
Definition: struct_var.h:237
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5256
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13101
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10413
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:98
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:350
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8714
static SCIP_RETCODE domAddHole(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:146
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:8896
#define SCIP_Real
Definition: def.h:127
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:104
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2639
SCIP_RETCODE SCIPdomchgApply(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, int depth, SCIP_Bool *cutoff)
Definition: var.c:1225
#define MIN(x, y)
Definition: memory.c:67
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5699
int parentvarssize
Definition: struct_var.h:252
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16340
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:238
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2228
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1795
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16262
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17522
#define SCIP_INVALID
Definition: def.h:147
internal methods for constraints and constraint handlers
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17156
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition: event.c:636
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2455
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2209
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3204
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:494
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10433
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:9941
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:365
SCIP_Real branchfactor
Definition: struct_var.h:203
unsigned int donotmultaggr
Definition: struct_var.h:270
#define SCIP_Longint
Definition: def.h:112
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5901
SCIP_Real nlpsol
Definition: struct_var.h:209
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:136
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2514
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15461
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17113
SCIP_Real lb
Definition: struct_var.h:159
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17281
SCIP_VAR * var
Definition: struct_lp.h:148
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5644
SCIP_RETCODE SCIPvarAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8605
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1799
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16380
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7983
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18616
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2779
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17087
SCIP_DOM glbdom
Definition: struct_var.h:217
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5064
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:642
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2423
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:58
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6221
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17313
SCIP_Bool collectvarhistory
Definition: struct_stat.h:227
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15737
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11461
SCIP_VAR * negatedvar
Definition: struct_var.h:234
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16710
#define EPSLE(x, y, eps)
Definition: def.h:154
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3143
SCIP_Real newbound
Definition: struct_var.h:107
int nlocksdown
Definition: struct_var.h:255
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3101
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8176
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15592
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6031
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6291
unsigned int delglobalstructs
Definition: struct_var.h:276
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5923
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12033
SCIP_RETCODE SCIPvarDropEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: var.c:17564
SCIP_Real rootsol
Definition: struct_var.h:204
#define EPSEQ(x, y, eps)
Definition: def.h:152
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2379
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2094
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16138
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16585
SCIP_HISTORY * history
Definition: struct_var.h:242
common defines and data types used in all packages of SCIP
SCIP_Longint nnodes
Definition: struct_stat.h:64
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15081
int nrootintfixingsrun
Definition: struct_stat.h:172
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16572
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11906
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:54
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17668
#define SCIP_CALL_ABORT(x)
Definition: def.h:245
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:76
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16058
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3080
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16562
SCIP_ORIGINAL original
Definition: struct_var.h:221
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17003
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3758
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16546
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17698
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17182
#define SCIP_ALLOC(x)
Definition: def.h:277
#define SCIPABORT()
Definition: def.h:238
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17457
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14991
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16687
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:561
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:55
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11821
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7917
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17057
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7083
unsigned int applied
Definition: struct_var.h:92
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:66
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10622
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16730
SCIP_HOLELIST ** ptr
Definition: struct_var.h:56
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17100
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16700
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17397
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:412
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:141
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16420
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5667
SCIP_COL * col
Definition: struct_var.h:222
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5490
SCIP_Real left
Definition: struct_var.h:42
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7194
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition: var.c:1348
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16849
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:444
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3259
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11016
SCIP_RETCODE SCIPprobAddVar(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var)
Definition: prob.c:893
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11728
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17638
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17499
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5710
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:13892
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:240
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14200
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1511
SCIP_RETCODE SCIProwAddConstant(SCIP_ROW *row, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp, SCIP_Real addval)
Definition: lp.c:5403
SCIP_Real scalar
Definition: struct_var.h:174
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:17811
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10682