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-2019 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 visit 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 "scip/cons.h"
38 #include "scip/event.h"
39 #include "scip/history.h"
40 #include "scip/implics.h"
41 #include "scip/lp.h"
42 #include "scip/primal.h"
43 #include "scip/prob.h"
44 #include "scip/pub_cons.h"
45 #include "scip/pub_history.h"
46 #include "scip/pub_implics.h"
47 #include "scip/pub_lp.h"
48 #include "scip/pub_message.h"
49 #include "scip/pub_misc.h"
50 #include "scip/pub_misc_sort.h"
51 #include "scip/pub_prop.h"
52 #include "scip/pub_var.h"
53 #include "scip/relax.h"
54 #include "scip/set.h"
55 #include "scip/sol.h"
56 #include "scip/stat.h"
57 #include "scip/struct_event.h"
58 #include "scip/struct_lp.h"
59 #include "scip/struct_prob.h"
60 #include "scip/struct_set.h"
61 #include "scip/struct_stat.h"
62 #include "scip/struct_var.h"
63 #include "scip/tree.h"
64 #include "scip/var.h"
65 #include <string.h>
66 
67 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
68  * in implication graph */
69 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
70 
71 /*
72  * hole, holelist, and domain methods
73  */
74 
75 /** creates a new holelist element */
76 static
78  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
79  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
80  SCIP_SET* set, /**< global SCIP settings */
81  SCIP_Real left, /**< left bound of open interval in new hole */
82  SCIP_Real right /**< right bound of open interval in new hole */
83  )
84 {
85  assert(holelist != NULL);
86  assert(blkmem != NULL);
87  assert(SCIPsetIsLT(set, left, right));
88 
89  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
90 
91  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
92  (*holelist)->hole.left = left;
93  (*holelist)->hole.right = right;
94  (*holelist)->next = NULL;
95 
96  return SCIP_OKAY;
97 }
98 
99 /** frees all elements in the holelist */
100 static
101 void holelistFree(
102  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
103  BMS_BLKMEM* blkmem /**< block memory for target holelist */
104  )
105 {
106  assert(holelist != NULL);
107  assert(blkmem != NULL);
108 
109  while( *holelist != NULL )
110  {
111  SCIP_HOLELIST* next;
112 
113  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
114  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
115 
116  next = (*holelist)->next;
117  BMSfreeBlockMemory(blkmem, holelist);
118  assert(*holelist == NULL);
119 
120  *holelist = next;
121  }
122  assert(*holelist == NULL);
123 }
124 
125 /** duplicates a list of holes */
126 static
128  SCIP_HOLELIST** target, /**< pointer to target holelist */
129  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
130  SCIP_SET* set, /**< global SCIP settings */
131  SCIP_HOLELIST* source /**< holelist to duplicate */
132  )
133 {
134  assert(target != NULL);
135 
136  while( source != NULL )
137  {
138  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
139  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
140  source = source->next;
141  target = &(*target)->next;
142  }
143 
144  return SCIP_OKAY;
145 }
146 
147 /** adds a hole to the domain */
148 static
150  SCIP_DOM* dom, /**< domain to add hole to */
151  BMS_BLKMEM* blkmem, /**< block memory */
152  SCIP_SET* set, /**< global SCIP settings */
153  SCIP_Real left, /**< left bound of open interval in new hole */
154  SCIP_Real right, /**< right bound of open interval in new hole */
155  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
156  )
157 {
158  SCIP_HOLELIST** insertpos;
159  SCIP_HOLELIST* next;
160 
161  assert(dom != NULL);
162  assert(added != NULL);
163 
164  /* search for the position of the new hole */
165  insertpos = &dom->holelist;
166  while( *insertpos != NULL && (*insertpos)->hole.left < left )
167  insertpos = &(*insertpos)->next;
168 
169  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
170  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
171  {
172  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
173  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
174  *added = FALSE;
175  return SCIP_OKAY;
176  }
177 
178  /* add hole */
179  *added = TRUE;
180 
181  next = *insertpos;
182  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
183  (*insertpos)->next = next;
184 
185  return SCIP_OKAY;
186 }
187 
188 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
189 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
190  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
191  * merge */
192 static
193 void domMerge(
194  SCIP_DOM* dom, /**< domain to merge */
195  BMS_BLKMEM* blkmem, /**< block memory */
196  SCIP_SET* set, /**< global SCIP settings */
197  SCIP_Real* newlb, /**< pointer to store new lower bound */
198  SCIP_Real* newub /**< pointer to store new upper bound */
199  )
200 {
201  SCIP_HOLELIST** holelistptr;
202  SCIP_HOLELIST** lastnextptr;
203  SCIP_Real* lastrightptr;
204 
205  assert(dom != NULL);
206  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
207 
208 #ifndef NDEBUG
209  {
210  /* check if the holelist is sorted w.r.t. to the left interval bounds */
211  SCIP_Real lastleft;
212 
213  holelistptr = &dom->holelist;
214 
215  lastleft = -SCIPsetInfinity(set);
216 
217  while( *holelistptr != NULL )
218  {
219  if( (*holelistptr)->next != NULL )
220  {
221  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
222  lastleft = (*holelistptr)->hole.left;
223  }
224 
225  holelistptr = &(*holelistptr)->next;
226  }
227  }
228 #endif
229 
230  SCIPsetDebugMsg(set, "merge hole list\n");
231 
232  holelistptr = &dom->holelist;
233  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
234  lastnextptr = holelistptr;
235 
236  while( *holelistptr != NULL )
237  {
238  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
239 
240  /* check that the hole is not empty */
241  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
242 
243  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
244  {
245  /* the remaining holes start behind the upper bound: remove them */
246  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
247  holelistFree(holelistptr, blkmem);
248  assert(*holelistptr == NULL);
249 
250  /* unlink this hole from the previous hole */
251  *lastnextptr = NULL;
252  }
253  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
254  {
255  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
256  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
257 
258  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
259 
260  /* adjust upper bound */
261  dom->ub = (*holelistptr)->hole.left;
262 
263  if(newub != NULL )
264  *newub = (*holelistptr)->hole.left;
265 
266  /* remove remaining hole list */
267  holelistFree(holelistptr, blkmem);
268  assert(*holelistptr == NULL);
269 
270  /* unlink this hole from the previous hole */
271  *lastnextptr = NULL;
272  }
273  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
274  {
275  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
276  * the last hole, delete this hole */
277  SCIP_HOLELIST* nextholelist;
278 
279  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
280  {
281  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
282  * the lower bound */
283  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
284  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
285 
286  /* adjust lower bound */
287  dom->lb = *lastrightptr;
288 
289  if(newlb != NULL )
290  *newlb = *lastrightptr;
291  }
292  else
293  {
294  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
295  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
296  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
297  }
298  nextholelist = (*holelistptr)->next;
299  (*holelistptr)->next = NULL;
300  holelistFree(holelistptr, blkmem);
301 
302  /* connect the linked list after removing the hole */
303  *lastnextptr = nextholelist;
304 
305  /* get next hole */
306  *holelistptr = nextholelist;
307  }
308  else
309  {
310  /* the holes do not overlap: update lastholelist and lastrightptr */
311  lastrightptr = &(*holelistptr)->hole.right;
312  lastnextptr = &(*holelistptr)->next;
313 
314  /* get next hole */
315  holelistptr = &(*holelistptr)->next;
316  }
317  }
318 
319 #ifndef NDEBUG
320  {
321  /* check that holes are merged */
322  SCIP_Real lastright;
323 
324  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
325  holelistptr = &dom->holelist;
326 
327  while( *holelistptr != NULL )
328  {
329  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
330  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
331 
332  /* check the hole property (check that the hole is not empty) */
333  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
334  lastright = (*holelistptr)->hole.right;
335 
336  /* get next hole */
337  holelistptr = &(*holelistptr)->next;
338  }
339 
340  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
341  assert( SCIPsetIsLE(set, lastright, dom->ub) );
342  }
343 #endif
344 }
345 
346 /*
347  * domain change methods
348  */
349 
350 /** ensures, that bound change info array for lower bound changes can store at least num entries */
351 static
353  SCIP_VAR* var, /**< problem variable */
354  BMS_BLKMEM* blkmem, /**< block memory */
355  SCIP_SET* set, /**< global SCIP settings */
356  int num /**< minimum number of entries to store */
357  )
358 {
359  assert(var != NULL);
360  assert(var->nlbchginfos <= var->lbchginfossize);
361  assert(SCIPvarIsTransformed(var));
362 
363  if( num > var->lbchginfossize )
364  {
365  int newsize;
366 
367  newsize = SCIPsetCalcMemGrowSize(set, num);
368  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
369  var->lbchginfossize = newsize;
370  }
371  assert(num <= var->lbchginfossize);
372 
373  return SCIP_OKAY;
374 }
375 
376 /** ensures, that bound change info array for upper bound changes can store at least num entries */
377 static
379  SCIP_VAR* var, /**< problem variable */
380  BMS_BLKMEM* blkmem, /**< block memory */
381  SCIP_SET* set, /**< global SCIP settings */
382  int num /**< minimum number of entries to store */
383  )
384 {
385  assert(var != NULL);
386  assert(var->nubchginfos <= var->ubchginfossize);
387  assert(SCIPvarIsTransformed(var));
388 
389  if( num > var->ubchginfossize )
390  {
391  int newsize;
392 
393  newsize = SCIPsetCalcMemGrowSize(set, num);
394  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
395  var->ubchginfossize = newsize;
396  }
397  assert(num <= var->ubchginfossize);
398 
399  return SCIP_OKAY;
400 }
401 
402 /** adds domain change info to the variable's lower bound change info array */
403 static
405  SCIP_VAR* var, /**< problem variable */
406  BMS_BLKMEM* blkmem, /**< block memory */
407  SCIP_SET* set, /**< global SCIP settings */
408  SCIP_Real oldbound, /**< old value for bound */
409  SCIP_Real newbound, /**< new value for bound */
410  int depth, /**< depth in the tree, where the bound change takes place */
411  int pos, /**< position of the bound change in its bound change array */
412  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
413  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
414  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
415  int inferinfo, /**< user information for inference to help resolving the conflict */
416  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
417  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
418  )
419 {
420  assert(var != NULL);
421  assert(SCIPsetIsLT(set, oldbound, newbound));
422  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
423  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
424  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
425  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
426  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
427  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
428  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
429 
430  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
431  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
432  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
433  oldbound, newbound);
434 
435  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
436  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
437  var->lbchginfos[var->nlbchginfos].newbound = newbound;
438  var->lbchginfos[var->nlbchginfos].var = var;
439  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
440  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
441  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
442  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
443  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
444  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
445  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
446  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
447  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
448 
449  /**@note The "pos" data member of the bound change info has a size of 27 bits */
450  assert(var->nlbchginfos < 1 << 27);
451 
452  switch( boundchgtype )
453  {
455  break;
457  assert(infercons != NULL);
458  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
459  break;
461  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
462  break;
463  default:
464  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
465  return SCIP_INVALIDDATA;
466  }
467 
468  var->nlbchginfos++;
469 
470  assert(var->nlbchginfos < 2
472  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
473 
474  return SCIP_OKAY;
475 }
476 
477 /** adds domain change info to the variable's upper bound change info array */
478 static
480  SCIP_VAR* var, /**< problem variable */
481  BMS_BLKMEM* blkmem, /**< block memory */
482  SCIP_SET* set, /**< global SCIP settings */
483  SCIP_Real oldbound, /**< old value for bound */
484  SCIP_Real newbound, /**< new value for bound */
485  int depth, /**< depth in the tree, where the bound change takes place */
486  int pos, /**< position of the bound change in its bound change array */
487  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
488  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
489  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
490  int inferinfo, /**< user information for inference to help resolving the conflict */
491  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
492  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
493  )
494 {
495  assert(var != NULL);
496  assert(SCIPsetIsGT(set, oldbound, newbound));
497  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
498  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
499  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
500  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
501  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
502  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
503  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
504 
505  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
506  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
507  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
508  oldbound, newbound);
509 
510  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
511  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
512  var->ubchginfos[var->nubchginfos].newbound = newbound;
513  var->ubchginfos[var->nubchginfos].var = var;
514  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
515  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
516  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
517  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
518  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
519  var->ubchginfos[var->nubchginfos].redundant = FALSE;
520  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
521  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
522  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
523 
524  /**@note The "pos" data member of the bound change info has a size of 27 bits */
525  assert(var->nubchginfos < 1 << 27);
526 
527  switch( boundchgtype )
528  {
530  break;
532  assert(infercons != NULL);
533  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
534  break;
536  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
537  break;
538  default:
539  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540  return SCIP_INVALIDDATA;
541  }
542 
543  var->nubchginfos++;
544 
545  assert(var->nubchginfos < 2
547  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
548 
549  return SCIP_OKAY;
550 }
551 
552 /** applies single bound change */
554  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
555  BMS_BLKMEM* blkmem, /**< block memory */
556  SCIP_SET* set, /**< global SCIP settings */
557  SCIP_STAT* stat, /**< problem statistics */
558  SCIP_LP* lp, /**< current LP data */
559  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
560  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
561  int depth, /**< depth in the tree, where the bound change takes place */
562  int pos, /**< position of the bound change in its bound change array */
563  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
564  )
565 {
566  SCIP_VAR* var;
567 
568  assert(boundchg != NULL);
569  assert(stat != NULL);
570  assert(depth > 0);
571  assert(pos >= 0);
572  assert(cutoff != NULL);
573 
574  *cutoff = FALSE;
575 
576  /* ignore redundant bound changes */
577  if( boundchg->redundant )
578  return SCIP_OKAY;
579 
580  var = boundchg->var;
581  assert(var != NULL);
583  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
584 
585  /* apply bound change */
586  switch( boundchg->boundtype )
587  {
589  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
590  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
591  {
592  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
593  {
594  /* add the bound change info to the variable's bound change info array */
595  switch( boundchg->boundchgtype )
596  {
598  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
599  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
600  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
602  stat->lastbranchvar = var;
604  stat->lastbranchvalue = boundchg->newbound;
605  break;
606 
608  assert(boundchg->data.inferencedata.reason.cons != NULL);
609  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
610  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
611  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
612  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
613  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
614  boundchg->data.inferencedata.info,
616  break;
617 
619  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
620  boundchg->data.inferencedata.reason.prop != NULL
621  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
622  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
623  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
624  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
625  boundchg->data.inferencedata.info,
627  break;
628 
629  default:
630  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
631  return SCIP_INVALIDDATA;
632  }
633 
634  /* change local bound of variable */
635  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
636  }
637  else
638  {
639  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
640  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
641  *cutoff = TRUE;
642  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
643  }
644  }
645  else
646  {
647  /* mark bound change to be inactive */
648  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
649  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
650  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
651  boundchg->redundant = TRUE;
652  }
653  break;
654 
656  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
657  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
658  {
659  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
660  {
661  /* add the bound change info to the variable's bound change info array */
662  switch( boundchg->boundchgtype )
663  {
665  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
666  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
667  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
669  stat->lastbranchvar = var;
671  stat->lastbranchvalue = boundchg->newbound;
672  break;
673 
675  assert(boundchg->data.inferencedata.reason.cons != NULL);
676  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
677  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
678  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
679  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
680  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
681  boundchg->data.inferencedata.info,
683  break;
684 
686  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
687  boundchg->data.inferencedata.reason.prop != NULL
688  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
689  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
690  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
691  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
692  boundchg->data.inferencedata.info,
694  break;
695 
696  default:
697  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
698  return SCIP_INVALIDDATA;
699  }
700 
701  /* change local bound of variable */
702  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
703  }
704  else
705  {
706  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
707  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
708  *cutoff = TRUE;
709  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
710  }
711  }
712  else
713  {
714  /* mark bound change to be inactive */
715  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
716  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
717  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
718  boundchg->redundant = TRUE;
719  }
720  break;
721 
722  default:
723  SCIPerrorMessage("unknown bound type\n");
724  return SCIP_INVALIDDATA;
725  }
726 
727  /* update the branching and inference history */
728  if( !boundchg->applied && !boundchg->redundant )
729  {
730  assert(var == boundchg->var);
731 
733  {
734  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
737  }
738  else if( stat->lastbranchvar != NULL )
739  {
740  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
741  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
742  }
743  boundchg->applied = TRUE;
744  }
745 
746  return SCIP_OKAY;
747 }
748 
749 /** undoes single bound change */
751  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
752  BMS_BLKMEM* blkmem, /**< block memory */
753  SCIP_SET* set, /**< global SCIP settings */
754  SCIP_STAT* stat, /**< problem statistics */
755  SCIP_LP* lp, /**< current LP data */
756  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
757  SCIP_EVENTQUEUE* eventqueue /**< event queue */
758  )
759 {
760  SCIP_VAR* var;
761 
762  assert(boundchg != NULL);
763  assert(stat != NULL);
764 
765  /* ignore redundant bound changes */
766  if( boundchg->redundant )
767  return SCIP_OKAY;
768 
769  var = boundchg->var;
770  assert(var != NULL);
772 
773  /* undo bound change: apply the previous bound change of variable */
774  switch( boundchg->boundtype )
775  {
777  var->nlbchginfos--;
778  assert(var->nlbchginfos >= 0);
779  assert(var->lbchginfos != NULL);
780  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
781  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
782 
783  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
784  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
787 
788  /* reinstall the previous local bound */
789  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
790  var->lbchginfos[var->nlbchginfos].oldbound) );
791 
792  /* in case all bound changes are removed the local bound should match the global bound */
793  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
794 
795  break;
796 
798  var->nubchginfos--;
799  assert(var->nubchginfos >= 0);
800  assert(var->ubchginfos != NULL);
801  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
802  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
803 
804  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
805  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
808 
809  /* reinstall the previous local bound */
810  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
811  var->ubchginfos[var->nubchginfos].oldbound) );
812 
813  /* in case all bound changes are removed the local bound should match the global bound */
814  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
815 
816  break;
817 
818  default:
819  SCIPerrorMessage("unknown bound type\n");
820  return SCIP_INVALIDDATA;
821  }
822 
823  /* update last branching variable */
825  {
826  stat->lastbranchvar = NULL;
828  }
829 
830  return SCIP_OKAY;
831 }
832 
833 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
834 static
836  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
837  BMS_BLKMEM* blkmem, /**< block memory */
838  SCIP_SET* set, /**< global SCIP settings */
839  SCIP_STAT* stat, /**< problem statistics */
840  SCIP_LP* lp, /**< current LP data */
841  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
842  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
843  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
844  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
845  )
846 {
847  SCIP_VAR* var;
848  SCIP_Real newbound;
849  SCIP_BOUNDTYPE boundtype;
850 
851  assert(boundchg != NULL);
852  assert(cutoff != NULL);
853 
854  *cutoff = FALSE;
855 
856  /* ignore redundant bound changes */
857  if( boundchg->redundant )
858  return SCIP_OKAY;
859 
860  var = SCIPboundchgGetVar(boundchg);
861  newbound = SCIPboundchgGetNewbound(boundchg);
862  boundtype = SCIPboundchgGetBoundtype(boundchg);
863 
864  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
865  * after that bound change was applied
866  *
867  * @note a global bound change is not captured by the redundant member of the bound change data structure
868  */
869  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
870  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
871  {
872  return SCIP_OKAY;
873  }
874 
875  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
877  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
878 
879  /* check for cutoff */
880  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
881  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
882  {
883  *cutoff = TRUE;
884  return SCIP_OKAY;
885  }
886 
887  /* apply bound change */
888  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
889 
890  return SCIP_OKAY;
891 }
892 
893 /** captures branching and inference data of bound change */
894 static
896  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
897  )
898 {
899  assert(boundchg != NULL);
900 
901  /* capture variable associated with the bound change */
902  assert(boundchg->var != NULL);
903  SCIPvarCapture(boundchg->var);
904 
905  switch( boundchg->boundchgtype )
906  {
909  break;
910 
912  assert(boundchg->data.inferencedata.var != NULL);
913  assert(boundchg->data.inferencedata.reason.cons != NULL);
914  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
915  break;
916 
917  default:
918  SCIPerrorMessage("invalid bound change type\n");
919  return SCIP_INVALIDDATA;
920  }
921 
922  return SCIP_OKAY;
923 }
924 
925 /** releases branching and inference data of bound change */
926 static
928  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
929  BMS_BLKMEM* blkmem, /**< block memory */
930  SCIP_SET* set, /**< global SCIP settings */
931  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
932  SCIP_LP* lp /**< current LP data */
933 
934  )
935 {
936  assert(boundchg != NULL);
937 
938  switch( boundchg->boundchgtype )
939  {
942  break;
943 
945  assert(boundchg->data.inferencedata.var != NULL);
946  assert(boundchg->data.inferencedata.reason.cons != NULL);
947  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
948  break;
949 
950  default:
951  SCIPerrorMessage("invalid bound change type\n");
952  return SCIP_INVALIDDATA;
953  }
954 
955  /* release variable */
956  assert(boundchg->var != NULL);
957  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, " -> %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  SCIPsetDebugMsg(set, " -> %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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, " -> %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  SCIPsetDebugMsg(set, " -> %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  SCIPsetDebugMsg(set, "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  SCIPsetDebugMsg(set, " -> %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  SCIPsetDebugMsg(set, "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", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1376  newbound, var->name, (void*)domchg, (void*)*domchg);
1377 
1378  /* if domain change data doesn't exist, create it;
1379  * if domain change is static, convert it into dynamic change
1380  */
1381  if( *domchg == NULL )
1382  {
1383  SCIP_CALL( domchgCreate(domchg, blkmem) );
1384  }
1385  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1386  {
1387  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1388  }
1389  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1390 
1391  /* get memory for additional bound change */
1392  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1393 
1394  /* fill in the bound change data */
1395  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1396  boundchg->var = var;
1397  switch( boundchgtype )
1398  {
1400  boundchg->data.branchingdata.lpsolval = lpsolval;
1401  break;
1403  assert(infercons != NULL);
1404  boundchg->data.inferencedata.var = infervar;
1405  boundchg->data.inferencedata.reason.cons = infercons;
1406  boundchg->data.inferencedata.info = inferinfo;
1407  break;
1409  boundchg->data.inferencedata.var = infervar;
1410  boundchg->data.inferencedata.reason.prop = inferprop;
1411  boundchg->data.inferencedata.info = inferinfo;
1412  break;
1413  default:
1414  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1415  return SCIP_INVALIDDATA;
1416  }
1417 
1418  boundchg->newbound = newbound;
1419  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1420  boundchg->boundtype = boundtype; /*lint !e641*/
1421  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1422  boundchg->applied = FALSE;
1423  boundchg->redundant = FALSE;
1424  (*domchg)->domchgdyn.nboundchgs++;
1425 
1426  /* capture branching and inference data associated with the bound changes */
1427  SCIP_CALL( boundchgCaptureData(boundchg) );
1428 
1429 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1430 #ifdef SCIP_MORE_DEBUG
1431  {
1432  int i;
1433  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1434  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1435  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1436  }
1437 #endif
1438 #endif
1439 
1440  return SCIP_OKAY;
1441 }
1442 
1443 /** adds hole change to domain changes */
1445  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1446  BMS_BLKMEM* blkmem, /**< block memory */
1447  SCIP_SET* set, /**< global SCIP settings */
1448  SCIP_HOLELIST** ptr, /**< changed list pointer */
1449  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1450  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1451  )
1452 {
1453  SCIP_HOLECHG* holechg;
1454 
1455  assert(domchg != NULL);
1456  assert(ptr != NULL);
1457 
1458  /* if domain change data doesn't exist, create it;
1459  * if domain change is static, convert it into dynamic change
1460  */
1461  if( *domchg == NULL )
1462  {
1463  SCIP_CALL( domchgCreate(domchg, blkmem) );
1464  }
1465  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1466  {
1467  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1468  }
1469  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1470 
1471  /* get memory for additional hole change */
1472  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1473 
1474  /* fill in the hole change data */
1475  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1476  holechg->ptr = ptr;
1477  holechg->newlist = newlist;
1478  holechg->oldlist = oldlist;
1479  (*domchg)->domchgdyn.nholechgs++;
1480 
1481  return SCIP_OKAY;
1482 }
1483 
1484 
1485 
1486 
1487 /*
1488  * methods for variables
1489  */
1490 
1491 /** returns adjusted lower bound value, which is rounded for integral variable types */
1492 static
1494  SCIP_SET* set, /**< global SCIP settings */
1495  SCIP_VARTYPE vartype, /**< type of variable */
1496  SCIP_Real lb /**< lower bound to adjust */
1497  )
1498 {
1499  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1500  return -SCIPsetInfinity(set);
1501  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1502  return SCIPsetInfinity(set);
1503  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1504  return SCIPsetFeasCeil(set, lb);
1505  else if( SCIPsetIsZero(set, lb) )
1506  return 0.0;
1507  else
1508  return lb;
1509 }
1510 
1511 /** returns adjusted upper bound value, which is rounded for integral variable types */
1512 static
1514  SCIP_SET* set, /**< global SCIP settings */
1515  SCIP_VARTYPE vartype, /**< type of variable */
1516  SCIP_Real ub /**< upper bound to adjust */
1517  )
1518 {
1519  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1520  return SCIPsetInfinity(set);
1521  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1522  return -SCIPsetInfinity(set);
1523  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1524  return SCIPsetFeasFloor(set, ub);
1525  else if( SCIPsetIsZero(set, ub) )
1526  return 0.0;
1527  else
1528  return ub;
1529 }
1530 
1531 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1532  * bounds arrays, and optionally removes them also from the variable itself
1533  */
1535  SCIP_VAR* var, /**< problem variable */
1536  BMS_BLKMEM* blkmem, /**< block memory */
1537  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1538  SCIP_SET* set, /**< global SCIP settings */
1539  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1540  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1541  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1542  )
1543 {
1544  SCIP_Real lb;
1545  SCIP_Real ub;
1546 
1547  assert(var != NULL);
1549  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1550 
1551  lb = SCIPvarGetLbGlobal(var);
1552  ub = SCIPvarGetUbGlobal(var);
1553 
1554  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1555  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1556 
1557  /* remove implications of (fixed) binary variable */
1558  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1559  {
1560  SCIP_Bool varfixing;
1561 
1562  assert(SCIPvarIsBinary(var));
1563 
1564  varfixing = FALSE;
1565  do
1566  {
1567  SCIP_VAR** implvars;
1568  SCIP_BOUNDTYPE* impltypes;
1569  int nimpls;
1570  int i;
1571 
1572  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1573  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1574  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1575 
1576  for( i = 0; i < nimpls; i++ )
1577  {
1578  SCIP_VAR* implvar;
1579  SCIP_BOUNDTYPE impltype;
1580 
1581  implvar = implvars[i];
1582  impltype = impltypes[i];
1583  assert(implvar != var);
1584 
1585  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1586  * the following variable bound from x's variable bounds
1587  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1588  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1589  */
1590  if( impltype == SCIP_BOUNDTYPE_UPPER )
1591  {
1592  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1593  {
1594  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1595  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1596  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1597  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1598  implvar->closestvblpcount = -1;
1599  var->closestvblpcount = -1;
1600  }
1601  }
1602  else
1603  {
1604  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1605  {
1606  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1607  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1608  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1609  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1610  implvar->closestvblpcount = -1;
1611  var->closestvblpcount = -1;
1612  }
1613  }
1614  }
1615  varfixing = !varfixing;
1616  }
1617  while( varfixing == TRUE );
1618 
1619  if( removefromvar )
1620  {
1621  /* free the implications data structures */
1622  SCIPimplicsFree(&var->implics, blkmem);
1623  }
1624  }
1625 
1626  /* remove the (redundant) variable lower bounds */
1627  if( var->vlbs != NULL )
1628  {
1629  SCIP_VAR** vars;
1630  SCIP_Real* coefs;
1631  SCIP_Real* constants;
1632  int nvbds;
1633  int newnvbds;
1634  int i;
1635 
1636  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1637  vars = SCIPvboundsGetVars(var->vlbs);
1638  coefs = SCIPvboundsGetCoefs(var->vlbs);
1639  constants = SCIPvboundsGetConstants(var->vlbs);
1640 
1641  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1642  * z == ub ==> x >= b*ub + d , if b > 0
1643  * z == lb ==> x >= b*lb + d , if b < 0
1644  */
1645  newnvbds = 0;
1646  for( i = 0; i < nvbds; i++ )
1647  {
1648  SCIP_VAR* implvar;
1649  SCIP_Real coef;
1650 
1651  assert(newnvbds <= i);
1652 
1653  implvar = vars[i];
1654  assert(implvar != NULL);
1655 
1656  coef = coefs[i];
1657  assert(!SCIPsetIsZero(set, coef));
1658 
1659  /* check, if we want to remove the variable bound */
1660  if( onlyredundant )
1661  {
1662  SCIP_Real vbound;
1663 
1664  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1665  if( SCIPsetIsFeasGT(set, vbound, lb) )
1666  {
1667  /* the variable bound is not redundant: keep it */
1668  if( removefromvar )
1669  {
1670  if( newnvbds < i )
1671  {
1672  vars[newnvbds] = implvar;
1673  coefs[newnvbds] = coef;
1674  constants[newnvbds] = constants[i];
1675  }
1676  newnvbds++;
1677  }
1678  continue;
1679  }
1680  }
1681 
1682  /* remove the corresponding implication */
1683  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1684  {
1685  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1686  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1687  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1688  }
1689  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1690  {
1691  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1692  SCIPvarGetName(implvar), SCIPvarGetName(var));
1693  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1694  implvar->closestvblpcount = -1;
1695  var->closestvblpcount = -1;
1696  }
1697  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1698  {
1699  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1700  SCIPvarGetName(implvar), SCIPvarGetName(var));
1701  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1702  implvar->closestvblpcount = -1;
1703  var->closestvblpcount = -1;
1704  }
1705  }
1706 
1707  if( removefromvar )
1708  {
1709  /* update the number of variable bounds */
1710  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1711  var->closestvblpcount = -1;
1712  }
1713  }
1714 
1715  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1716  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1717  * cannot remove such variables x from z's implications.
1718  */
1719 
1720  /* remove the (redundant) variable upper bounds */
1721  if( var->vubs != NULL )
1722  {
1723  SCIP_VAR** vars;
1724  SCIP_Real* coefs;
1725  SCIP_Real* constants;
1726  int nvbds;
1727  int newnvbds;
1728  int i;
1729 
1730  nvbds = SCIPvboundsGetNVbds(var->vubs);
1731  vars = SCIPvboundsGetVars(var->vubs);
1732  coefs = SCIPvboundsGetCoefs(var->vubs);
1733  constants = SCIPvboundsGetConstants(var->vubs);
1734 
1735  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1736  * z == lb ==> x <= b*lb + d , if b > 0
1737  * z == ub ==> x <= b*ub + d , if b < 0
1738  */
1739  newnvbds = 0;
1740  for( i = 0; i < nvbds; i++ )
1741  {
1742  SCIP_VAR* implvar;
1743  SCIP_Real coef;
1744 
1745  assert(newnvbds <= i);
1746 
1747  implvar = vars[i];
1748  assert(implvar != NULL);
1749 
1750  coef = coefs[i];
1751  assert(!SCIPsetIsZero(set, coef));
1752 
1753  /* check, if we want to remove the variable bound */
1754  if( onlyredundant )
1755  {
1756  SCIP_Real vbound;
1757 
1758  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1759  if( SCIPsetIsFeasLT(set, vbound, ub) )
1760  {
1761  /* the variable bound is not redundant: keep it */
1762  if( removefromvar )
1763  {
1764  if( newnvbds < i )
1765  {
1766  vars[newnvbds] = implvar;
1767  coefs[newnvbds] = coefs[i];
1768  constants[newnvbds] = constants[i];
1769  }
1770  newnvbds++;
1771  }
1772  continue;
1773  }
1774  }
1775 
1776  /* remove the corresponding implication */
1777  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1778  {
1779  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1780  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1781  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1782  }
1783  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1784  {
1785  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1786  SCIPvarGetName(implvar), SCIPvarGetName(var));
1787  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1788  implvar->closestvblpcount = -1;
1789  var->closestvblpcount = -1;
1790  }
1791  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1792  {
1793  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1794  SCIPvarGetName(implvar), SCIPvarGetName(var));
1795  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1796  implvar->closestvblpcount = -1;
1797  var->closestvblpcount = -1;
1798  }
1799  }
1800 
1801  if( removefromvar )
1802  {
1803  /* update the number of variable bounds */
1804  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1805  var->closestvblpcount = -1;
1806  }
1807  }
1808 
1809  /* remove the variable from all cliques */
1810  if( SCIPvarIsBinary(var) )
1811  {
1812  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1813  SCIPcliquelistFree(&var->cliquelist, blkmem);
1814  }
1815 
1816  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1817  * z has no link (like in the binary case) to x
1818  */
1819 
1820  return SCIP_OKAY;
1821 }
1822 
1823 /** sets the variable name */
1824 static
1826  SCIP_VAR* var, /**< problem variable */
1827  BMS_BLKMEM* blkmem, /**< block memory */
1828  SCIP_STAT* stat, /**< problem statistics, or NULL */
1829  const char* name /**< name of variable, or NULL for automatic name creation */
1830  )
1831 {
1832  assert(blkmem != NULL);
1833  assert(var != NULL);
1834 
1835  if( name == NULL )
1836  {
1837  char s[SCIP_MAXSTRLEN];
1838 
1839  assert(stat != NULL);
1840 
1841  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1842  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1843  }
1844  else
1845  {
1846  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1847  }
1848 
1849  return SCIP_OKAY;
1850 }
1851 
1852 
1853 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1854  * with bounds zero and one is automatically converted into a binary variable
1855  */
1856 static
1858  SCIP_VAR** var, /**< pointer to variable data */
1859  BMS_BLKMEM* blkmem, /**< block memory */
1860  SCIP_SET* set, /**< global SCIP settings */
1861  SCIP_STAT* stat, /**< problem statistics */
1862  const char* name, /**< name of variable, or NULL for automatic name creation */
1863  SCIP_Real lb, /**< lower bound of variable */
1864  SCIP_Real ub, /**< upper bound of variable */
1865  SCIP_Real obj, /**< objective function value */
1866  SCIP_VARTYPE vartype, /**< type of variable */
1867  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1868  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1869  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1870  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1871  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1872  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1873  SCIP_VARDATA* vardata /**< user data for this specific variable */
1874  )
1875 {
1876  int i;
1877 
1878  assert(var != NULL);
1879  assert(blkmem != NULL);
1880  assert(stat != NULL);
1881 
1882  /* adjust bounds of variable */
1883  lb = adjustedLb(set, vartype, lb);
1884  ub = adjustedUb(set, vartype, ub);
1885 
1886  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1887  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1888  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1889  {
1890  if( vartype == SCIP_VARTYPE_INTEGER )
1891  vartype = SCIP_VARTYPE_BINARY;
1892  }
1893  else
1894  {
1895  if( vartype == SCIP_VARTYPE_BINARY )
1896  {
1897  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1898  return SCIP_INVALIDDATA;
1899  }
1900  }
1901 
1902  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1903  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1904 
1905  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1906 
1907  /* set variable's name */
1908  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1909 
1910 #ifndef NDEBUG
1911  (*var)->scip = set->scip;
1912 #endif
1913  (*var)->obj = obj;
1914  (*var)->unchangedobj = obj;
1915  (*var)->branchfactor = 1.0;
1916  (*var)->rootsol = 0.0;
1917  (*var)->bestrootsol = 0.0;
1918  (*var)->bestrootredcost = 0.0;
1919  (*var)->bestrootlpobjval = SCIP_INVALID;
1920  (*var)->relaxsol = 0.0;
1921  (*var)->nlpsol = 0.0;
1922  (*var)->primsolavg = 0.5 * (lb + ub);
1923  (*var)->conflictlb = SCIP_REAL_MIN;
1924  (*var)->conflictub = SCIP_REAL_MAX;
1925  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1926  (*var)->conflictrelaxedub = (*var)->conflictub;
1927  (*var)->lazylb = -SCIPsetInfinity(set);
1928  (*var)->lazyub = SCIPsetInfinity(set);
1929  (*var)->glbdom.holelist = NULL;
1930  (*var)->glbdom.lb = lb;
1931  (*var)->glbdom.ub = ub;
1932  (*var)->locdom.holelist = NULL;
1933  (*var)->locdom.lb = lb;
1934  (*var)->locdom.ub = ub;
1935  (*var)->varcopy = varcopy;
1936  (*var)->vardelorig = vardelorig;
1937  (*var)->vartrans = vartrans;
1938  (*var)->vardeltrans = vardeltrans;
1939  (*var)->vardata = vardata;
1940  (*var)->parentvars = NULL;
1941  (*var)->negatedvar = NULL;
1942  (*var)->vlbs = NULL;
1943  (*var)->vubs = NULL;
1944  (*var)->implics = NULL;
1945  (*var)->cliquelist = NULL;
1946  (*var)->eventfilter = NULL;
1947  (*var)->lbchginfos = NULL;
1948  (*var)->ubchginfos = NULL;
1949  (*var)->index = stat->nvaridx;
1950  (*var)->probindex = -1;
1951  (*var)->pseudocandindex = -1;
1952  (*var)->eventqueueindexobj = -1;
1953  (*var)->eventqueueindexlb = -1;
1954  (*var)->eventqueueindexub = -1;
1955  (*var)->parentvarssize = 0;
1956  (*var)->nparentvars = 0;
1957  (*var)->nuses = 0;
1958  (*var)->branchpriority = 0;
1959  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1960  (*var)->lbchginfossize = 0;
1961  (*var)->nlbchginfos = 0;
1962  (*var)->ubchginfossize = 0;
1963  (*var)->nubchginfos = 0;
1964  (*var)->conflictlbcount = 0;
1965  (*var)->conflictubcount = 0;
1966  (*var)->closestvlbidx = -1;
1967  (*var)->closestvubidx = -1;
1968  (*var)->closestvblpcount = -1;
1969  (*var)->initial = initial;
1970  (*var)->removable = removable;
1971  (*var)->deleted = FALSE;
1972  (*var)->donotmultaggr = FALSE;
1973  (*var)->vartype = vartype; /*lint !e641*/
1974  (*var)->pseudocostflag = FALSE;
1975  (*var)->eventqueueimpl = FALSE;
1976  (*var)->deletable = FALSE;
1977  (*var)->delglobalstructs = FALSE;
1978 
1979  for( i = 0; i < NLOCKTYPES; i++ )
1980  {
1981  (*var)->nlocksdown[i] = 0;
1982  (*var)->nlocksup[i] = 0;
1983  }
1984 
1985  stat->nvaridx++;
1986 
1987  /* create branching and inference history entries */
1988  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1989  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1990 
1991  /* the value based history is only created on demand */
1992  (*var)->valuehistory = NULL;
1993 
1994  return SCIP_OKAY;
1995 }
1996 
1997 /** creates and captures an original problem variable; an integer variable with bounds
1998  * zero and one is automatically converted into a binary variable
1999  */
2001  SCIP_VAR** var, /**< pointer to variable data */
2002  BMS_BLKMEM* blkmem, /**< block memory */
2003  SCIP_SET* set, /**< global SCIP settings */
2004  SCIP_STAT* stat, /**< problem statistics */
2005  const char* name, /**< name of variable, or NULL for automatic name creation */
2006  SCIP_Real lb, /**< lower bound of variable */
2007  SCIP_Real ub, /**< upper bound of variable */
2008  SCIP_Real obj, /**< objective function value */
2009  SCIP_VARTYPE vartype, /**< type of variable */
2010  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2011  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2012  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2013  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2014  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2015  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2016  SCIP_VARDATA* vardata /**< user data for this specific variable */
2017  )
2018 {
2019  assert(var != NULL);
2020  assert(blkmem != NULL);
2021  assert(stat != NULL);
2022 
2023  /* create variable */
2024  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2025  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2026 
2027  /* set variable status and data */
2028  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2029  (*var)->data.original.origdom.holelist = NULL;
2030  (*var)->data.original.origdom.lb = lb;
2031  (*var)->data.original.origdom.ub = ub;
2032  (*var)->data.original.transvar = NULL;
2033 
2034  /* capture variable */
2035  SCIPvarCapture(*var);
2036 
2037  return SCIP_OKAY;
2038 }
2039 
2040 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2041  * zero and one is automatically converted into a binary variable
2042  */
2044  SCIP_VAR** var, /**< pointer to variable data */
2045  BMS_BLKMEM* blkmem, /**< block memory */
2046  SCIP_SET* set, /**< global SCIP settings */
2047  SCIP_STAT* stat, /**< problem statistics */
2048  const char* name, /**< name of variable, or NULL for automatic name creation */
2049  SCIP_Real lb, /**< lower bound of variable */
2050  SCIP_Real ub, /**< upper bound of variable */
2051  SCIP_Real obj, /**< objective function value */
2052  SCIP_VARTYPE vartype, /**< type of variable */
2053  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2054  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2055  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2056  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2057  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2058  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2059  SCIP_VARDATA* vardata /**< user data for this specific variable */
2060  )
2061 {
2062  assert(var != NULL);
2063  assert(blkmem != NULL);
2064 
2065  /* create variable */
2066  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2067  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2068 
2069  /* create event filter for transformed variable */
2070  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2071 
2072  /* set variable status and data */
2073  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2074 
2075  /* capture variable */
2076  SCIPvarCapture(*var);
2077 
2078  return SCIP_OKAY;
2079 }
2080 
2081 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2082  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2083  * copied at all
2084  */
2086  SCIP_VAR** var, /**< pointer to store the target variable */
2087  BMS_BLKMEM* blkmem, /**< block memory */
2088  SCIP_SET* set, /**< global SCIP settings */
2089  SCIP_STAT* stat, /**< problem statistics */
2090  SCIP* sourcescip, /**< source SCIP data structure */
2091  SCIP_VAR* sourcevar, /**< source variable */
2092  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2093  * target variables */
2094  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2095  * target constraints */
2096  SCIP_Bool global /**< should global or local bounds be used? */
2097  )
2098 {
2099  SCIP_VARDATA* targetdata;
2100  SCIP_RESULT result;
2101  SCIP_Real lb;
2102  SCIP_Real ub;
2103 
2104  assert(set != NULL);
2105  assert(blkmem != NULL);
2106  assert(stat != NULL);
2107  assert(sourcescip != NULL);
2108  assert(sourcevar != NULL);
2109  assert(var != NULL);
2110  assert(set->stage == SCIP_STAGE_PROBLEM);
2111  assert(varmap != NULL);
2112  assert(consmap != NULL);
2113 
2114  /** @todo copy hole lists */
2115  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2116  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2117 
2118  result = SCIP_DIDNOTRUN;
2119  targetdata = NULL;
2120 
2121  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2122  {
2123  lb = SCIPvarGetLbOriginal(sourcevar);
2124  ub = SCIPvarGetUbOriginal(sourcevar);
2125  }
2126  else
2127  {
2128  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2129  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2130  }
2131 
2132  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2133  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2134  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2135  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2136  NULL, NULL, NULL, NULL, NULL) );
2137  assert(*var != NULL);
2138 
2139  /* directly copy donotmultaggr flag */
2140  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2141 
2142  /* insert variable into mapping between source SCIP and the target SCIP */
2143  assert(!SCIPhashmapExists(varmap, sourcevar));
2144  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2145 
2146  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2147  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2148  {
2149  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2150  varmap, consmap, (*var), &targetdata, &result) );
2151 
2152  /* evaluate result */
2153  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2154  {
2155  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2156  return SCIP_INVALIDRESULT;
2157  }
2158 
2159  assert(targetdata == NULL || result == SCIP_SUCCESS);
2160 
2161  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2162  if( result == SCIP_SUCCESS )
2163  {
2164  (*var)->varcopy = sourcevar->varcopy;
2165  (*var)->vardelorig = sourcevar->vardelorig;
2166  (*var)->vartrans = sourcevar->vartrans;
2167  (*var)->vardeltrans = sourcevar->vardeltrans;
2168  (*var)->vardata = targetdata;
2169  }
2170  }
2171 
2172  /* we initialize histories of the variables by copying the source variable-information */
2173  if( set->history_allowtransfer )
2174  {
2175  SCIPvarMergeHistories((*var), sourcevar, stat);
2176  }
2177 
2178  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2179  * methods
2180  */
2181  if( result == SCIP_SUCCESS )
2182  {
2183  (*var)->varcopy = sourcevar->varcopy;
2184  (*var)->vardelorig = sourcevar->vardelorig;
2185  (*var)->vartrans = sourcevar->vartrans;
2186  (*var)->vardeltrans = sourcevar->vardeltrans;
2187  (*var)->vardata = targetdata;
2188  }
2189 
2190  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2191 
2192  return SCIP_OKAY;
2193 }
2194 
2195 /** parse given string for a SCIP_Real bound */
2196 static
2198  SCIP_SET* set, /**< global SCIP settings */
2199  const char* str, /**< string to parse */
2200  SCIP_Real* value, /**< pointer to store the parsed value */
2201  char** endptr /**< pointer to store the final string position if successfully parsed */
2202  )
2203 {
2204  /* first check for infinity value */
2205  if( strncmp(str, "+inf", 4) == 0 )
2206  {
2207  *value = SCIPsetInfinity(set);
2208  (*endptr) = (char*)str + 4;
2209  }
2210  else if( strncmp(str, "-inf", 4) == 0 )
2211  {
2212  *value = -SCIPsetInfinity(set);
2213  (*endptr) = (char*)str + 4;
2214  }
2215  else
2216  {
2217  if( !SCIPstrToRealValue(str, value, endptr) )
2218  return SCIP_READERROR;
2219  }
2220 
2221  return SCIP_OKAY;
2222 }
2223 
2224 /** parse the characters as bounds */
2225 static
2227  SCIP_SET* set, /**< global SCIP settings */
2228  const char* str, /**< string to parse */
2229  char* type, /**< bound type (global, local, or lazy) */
2230  SCIP_Real* lb, /**< pointer to store the lower bound */
2231  SCIP_Real* ub, /**< pointer to store the upper bound */
2232  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2233  )
2234 {
2235  char token[SCIP_MAXSTRLEN];
2236  char* tmpend;
2237 
2238  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2239 
2240  /* get bound type */
2241  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2242  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2243  {
2244  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2245  *endptr = NULL;
2246  return SCIP_OKAY;
2247  }
2248 
2249  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2250 
2251  /* get lower bound */
2252  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2253  str = *endptr;
2254  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2255 
2256  /* get upper bound */
2257  SCIP_CALL( parseValue(set, str, ub, endptr) );
2258 
2259  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2260 
2261  /* skip end of bounds */
2262  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2263  ++(*endptr);
2264 
2265  return SCIP_OKAY;
2266 }
2267 
2268 /** parses a given string for a variable informations */
2269 static
2271  SCIP_SET* set, /**< global SCIP settings */
2272  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2273  const char* str, /**< string to parse */
2274  char* name, /**< pointer to store the variable name */
2275  SCIP_Real* lb, /**< pointer to store the lower bound */
2276  SCIP_Real* ub, /**< pointer to store the upper bound */
2277  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2278  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2279  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2280  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2281  SCIP_Bool local, /**< should the local bound be applied */
2282  char** endptr, /**< pointer to store the final string position if successfully */
2283  SCIP_Bool* success /**< pointer store if the paring process was successful */
2284  )
2285 {
2286  SCIP_Real parsedlb;
2287  SCIP_Real parsedub;
2288  char token[SCIP_MAXSTRLEN];
2289  char* strptr;
2290  int i;
2291 
2292  assert(lb != NULL);
2293  assert(ub != NULL);
2294  assert(obj != NULL);
2295  assert(vartype != NULL);
2296  assert(lazylb != NULL);
2297  assert(lazyub != NULL);
2298  assert(success != NULL);
2299 
2300  (*success) = TRUE;
2301 
2302  /* copy variable type */
2303  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2304  assert(str != *endptr);
2305  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2306 
2307  /* get variable type */
2308  if( strncmp(token, "binary", 3) == 0 )
2309  (*vartype) = SCIP_VARTYPE_BINARY;
2310  else if( strncmp(token, "integer", 3) == 0 )
2311  (*vartype) = SCIP_VARTYPE_INTEGER;
2312  else if( strncmp(token, "implicit", 3) == 0 )
2313  (*vartype) = SCIP_VARTYPE_IMPLINT;
2314  else if( strncmp(token, "continuous", 3) == 0 )
2315  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2316  else
2317  {
2318  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2319  (*success) = FALSE;
2320  return SCIP_OKAY;
2321  }
2322 
2323  /* move string pointer behind variable type */
2324  str = *endptr;
2325 
2326  /* get variable name */
2327  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2328  assert(endptr != NULL);
2329  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2330 
2331  /* move string pointer behind variable name */
2332  str = *endptr;
2333 
2334  /* cut out objective coefficient */
2335  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2336 
2337  /* move string pointer behind objective coefficient */
2338  str = *endptr;
2339 
2340  /* get objective coefficient */
2341  if( !SCIPstrToRealValue(token, obj, endptr) )
2342  {
2343  *endptr = NULL;
2344  return SCIP_READERROR;
2345  }
2346 
2347  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2348 
2349  /* parse global/original bounds */
2350  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2351  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2352 
2353  /* initialize the lazy bound */
2354  *lazylb = -SCIPsetInfinity(set);
2355  *lazyub = SCIPsetInfinity(set);
2356 
2357  /* store pointer */
2358  strptr = *endptr;
2359 
2360  /* possibly parse optional local and lazy bounds */
2361  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2362  {
2363  /* start after previous bounds */
2364  strptr = *endptr;
2365 
2366  /* parse global bounds */
2367  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2368 
2369  /* stop if parsing of bounds failed */
2370  if( *endptr == NULL )
2371  break;
2372 
2373  if( strncmp(token, "local", 5) == 0 && local )
2374  {
2375  *lb = parsedlb;
2376  *ub = parsedub;
2377  }
2378  else if( strncmp(token, "lazy", 4) == 0 )
2379  {
2380  *lazylb = parsedlb;
2381  *lazyub = parsedub;
2382  }
2383  }
2384 
2385  /* restore pointer */
2386  if ( *endptr == NULL )
2387  *endptr = strptr;
2388 
2389  /* check bounds for binary variables */
2390  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2391  {
2392  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2393  {
2394  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2395  return SCIP_READERROR;
2396  }
2397  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2398  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2399  {
2400  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2401  return SCIP_READERROR;
2402  }
2403  }
2404 
2405  return SCIP_OKAY;
2406 }
2407 
2408 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2409  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2410  * integer variable with bounds zero and one is automatically converted into a binary variable
2411  */
2413  SCIP_VAR** var, /**< pointer to variable data */
2414  BMS_BLKMEM* blkmem, /**< block memory */
2415  SCIP_SET* set, /**< global SCIP settings */
2416  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2417  SCIP_STAT* stat, /**< problem statistics */
2418  const char* str, /**< string to parse */
2419  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2420  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2421  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2422  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2423  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2424  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2425  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2426  char** endptr, /**< pointer to store the final string position if successfully */
2427  SCIP_Bool* success /**< pointer store if the paring process was successful */
2428  )
2429 {
2430  char name[SCIP_MAXSTRLEN];
2431  SCIP_Real lb;
2432  SCIP_Real ub;
2433  SCIP_Real obj;
2434  SCIP_VARTYPE vartype;
2435  SCIP_Real lazylb;
2436  SCIP_Real lazyub;
2437 
2438  assert(var != NULL);
2439  assert(blkmem != NULL);
2440  assert(stat != NULL);
2441  assert(endptr != NULL);
2442  assert(success != NULL);
2443 
2444  /* parse string in cip format for variable information */
2445  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2446 
2447  if( *success )
2448  {
2449  /* create variable */
2450  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2451  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2452 
2453  /* set variable status and data */
2454  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2455  (*var)->data.original.origdom.holelist = NULL;
2456  (*var)->data.original.origdom.lb = lb;
2457  (*var)->data.original.origdom.ub = ub;
2458  (*var)->data.original.transvar = NULL;
2459 
2460  /* set lazy status of variable bounds */
2461  (*var)->lazylb = lazylb;
2462  (*var)->lazyub = lazyub;
2463 
2464  /* capture variable */
2465  SCIPvarCapture(*var);
2466  }
2467 
2468  return SCIP_OKAY;
2469 }
2470 
2471 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2472  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2473  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2474  * variable
2475  */
2477  SCIP_VAR** var, /**< pointer to variable data */
2478  BMS_BLKMEM* blkmem, /**< block memory */
2479  SCIP_SET* set, /**< global SCIP settings */
2480  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2481  SCIP_STAT* stat, /**< problem statistics */
2482  const char* str, /**< string to parse */
2483  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2484  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2485  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2486  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2487  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2488  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2489  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2490  char** endptr, /**< pointer to store the final string position if successfully */
2491  SCIP_Bool* success /**< pointer store if the paring process was successful */
2492  )
2493 {
2494  char name[SCIP_MAXSTRLEN];
2495  SCIP_Real lb;
2496  SCIP_Real ub;
2497  SCIP_Real obj;
2498  SCIP_VARTYPE vartype;
2499  SCIP_Real lazylb;
2500  SCIP_Real lazyub;
2501 
2502  assert(var != NULL);
2503  assert(blkmem != NULL);
2504  assert(endptr != NULL);
2505  assert(success != NULL);
2506 
2507  /* parse string in cip format for variable information */
2508  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2509 
2510  if( *success )
2511  {
2512  /* create variable */
2513  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2514  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2515 
2516  /* create event filter for transformed variable */
2517  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2518 
2519  /* set variable status and data */
2520  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2521 
2522  /* set lazy status of variable bounds */
2523  (*var)->lazylb = lazylb;
2524  (*var)->lazyub = lazyub;
2525 
2526  /* capture variable */
2527  SCIPvarCapture(*var);
2528  }
2529 
2530  return SCIP_OKAY;
2531 }
2532 
2533 /** ensures, that parentvars array of var can store at least num entries */
2534 static
2536  SCIP_VAR* var, /**< problem variable */
2537  BMS_BLKMEM* blkmem, /**< block memory */
2538  SCIP_SET* set, /**< global SCIP settings */
2539  int num /**< minimum number of entries to store */
2540  )
2541 {
2542  assert(var->nparentvars <= var->parentvarssize);
2543 
2544  if( num > var->parentvarssize )
2545  {
2546  int newsize;
2547 
2548  newsize = SCIPsetCalcMemGrowSize(set, num);
2549  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2550  var->parentvarssize = newsize;
2551  }
2552  assert(num <= var->parentvarssize);
2553 
2554  return SCIP_OKAY;
2555 }
2556 
2557 /** adds variable to parent list of a variable and captures parent variable */
2558 static
2560  SCIP_VAR* var, /**< variable to add parent to */
2561  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2562  SCIP_SET* set, /**< global SCIP settings */
2563  SCIP_VAR* parentvar /**< parent variable to add */
2564  )
2565 {
2566  assert(var != NULL);
2567  assert(parentvar != NULL);
2568 
2569  /* the direct original counterpart must be stored as first parent */
2570  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2571 
2572  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2573  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2574 
2575  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2576 
2577  var->parentvars[var->nparentvars] = parentvar;
2578  var->nparentvars++;
2579 
2580  SCIPvarCapture(parentvar);
2581 
2582  return SCIP_OKAY;
2583 }
2584 
2585 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2586 static
2588  SCIP_VAR** var, /**< pointer to variable */
2589  BMS_BLKMEM* blkmem, /**< block memory */
2590  SCIP_SET* set, /**< global SCIP settings */
2591  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2592  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2593  )
2594 {
2595  SCIP_VAR* parentvar;
2596  int i;
2597 
2598  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2599 
2600  /* release the parent variables and remove the link from the parent variable to the child */
2601  for( i = 0; i < (*var)->nparentvars; ++i )
2602  {
2603  assert((*var)->parentvars != NULL);
2604  parentvar = (*var)->parentvars[i];
2605  assert(parentvar != NULL);
2606 
2607  switch( SCIPvarGetStatus(parentvar) )
2608  {
2610  assert(parentvar->data.original.transvar == *var);
2611  assert(&parentvar->data.original.transvar != var);
2612  parentvar->data.original.transvar = NULL;
2613  break;
2614 
2616  assert(parentvar->data.aggregate.var == *var);
2617  assert(&parentvar->data.aggregate.var != var);
2618  parentvar->data.aggregate.var = NULL;
2619  break;
2620 
2621 #if 0
2622  /* The following code is unclear: should the current variable be removed from its parents? */
2624  assert(parentvar->data.multaggr.vars != NULL);
2625  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2626  {}
2627  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2628  if( v < parentvar->data.multaggr.nvars-1 )
2629  {
2630  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2631  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2632  }
2633  parentvar->data.multaggr.nvars--;
2634  break;
2635 #endif
2636 
2638  assert(parentvar->negatedvar == *var);
2639  assert((*var)->negatedvar == parentvar);
2640  parentvar->negatedvar = NULL;
2641  (*var)->negatedvar = NULL;
2642  break;
2643 
2644  default:
2645  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2646  return SCIP_INVALIDDATA;
2647  } /*lint !e788*/
2648 
2649  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2650  }
2651 
2652  /* free parentvars array */
2653  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2654 
2655  return SCIP_OKAY;
2656 }
2657 
2658 /** frees a variable */
2659 static
2661  SCIP_VAR** var, /**< pointer to variable */
2662  BMS_BLKMEM* blkmem, /**< block memory */
2663  SCIP_SET* set, /**< global SCIP settings */
2664  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2665  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2666  )
2667 {
2668  assert(var != NULL);
2669  assert(*var != NULL);
2670  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2671  assert((*var)->nuses == 0);
2672  assert((*var)->probindex == -1);
2673 
2674  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2675 
2676  switch( SCIPvarGetStatus(*var) )
2677  {
2679  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2680  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2681  assert((*var)->data.original.origdom.holelist == NULL);
2682  break;
2683  case SCIP_VARSTATUS_LOOSE:
2684  break;
2685  case SCIP_VARSTATUS_COLUMN:
2686  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2687  break;
2688  case SCIP_VARSTATUS_FIXED:
2690  break;
2692  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2693  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2694  break;
2696  break;
2697  default:
2698  SCIPerrorMessage("unknown variable status\n");
2699  return SCIP_INVALIDDATA;
2700  }
2701 
2702  /* release all parent variables and free the parentvars array */
2703  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2704 
2705  /* free user data */
2707  {
2708  if( (*var)->vardelorig != NULL )
2709  {
2710  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2711  }
2712  }
2713  else
2714  {
2715  if( (*var)->vardeltrans != NULL )
2716  {
2717  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2718  }
2719  }
2720 
2721  /* free event filter */
2722  if( (*var)->eventfilter != NULL )
2723  {
2724  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2725  }
2726  assert((*var)->eventfilter == NULL);
2727 
2728  /* free hole lists */
2729  holelistFree(&(*var)->glbdom.holelist, blkmem);
2730  holelistFree(&(*var)->locdom.holelist, blkmem);
2731  assert((*var)->glbdom.holelist == NULL);
2732  assert((*var)->locdom.holelist == NULL);
2733 
2734  /* free variable bounds data structures */
2735  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2736  SCIPvboundsFree(&(*var)->vubs, blkmem);
2737 
2738  /* free implications data structures */
2739  SCIPimplicsFree(&(*var)->implics, blkmem);
2740 
2741  /* free clique list data structures */
2742  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2743 
2744  /* free bound change information arrays */
2745  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2746  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2747 
2748  /* free branching and inference history entries */
2749  SCIPhistoryFree(&(*var)->history, blkmem);
2750  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2751  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2752 
2753  /* free variable data structure */
2754  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2755  BMSfreeBlockMemory(blkmem, var);
2756 
2757  return SCIP_OKAY;
2758 }
2759 
2760 /** increases usage counter of variable */
2761 void SCIPvarCapture(
2762  SCIP_VAR* var /**< variable */
2763  )
2764 {
2765  assert(var != NULL);
2766  assert(var->nuses >= 0);
2767 
2768  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2769  var->nuses++;
2770 }
2771 
2772 /** decreases usage counter of variable, and frees memory if necessary */
2774  SCIP_VAR** var, /**< pointer to variable */
2775  BMS_BLKMEM* blkmem, /**< block memory */
2776  SCIP_SET* set, /**< global SCIP settings */
2777  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2778  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2779  )
2780 {
2781  assert(var != NULL);
2782  assert(*var != NULL);
2783  assert((*var)->nuses >= 1);
2784  assert(blkmem != NULL);
2785  assert((*var)->scip == set->scip);
2786 
2787  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2788  (*var)->nuses--;
2789  if( (*var)->nuses == 0 )
2790  {
2791  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2792  }
2793 
2794  *var = NULL;
2795 
2796  return SCIP_OKAY;
2797 }
2798 
2799 /** change variable name */
2801  SCIP_VAR* var, /**< problem variable */
2802  BMS_BLKMEM* blkmem, /**< block memory */
2803  const char* name /**< name of variable */
2804  )
2805 {
2806  assert(name != NULL);
2807 
2808  /* remove old variable name */
2809  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2810 
2811  /* set new variable name */
2812  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2813 
2814  return SCIP_OKAY;
2815 }
2816 
2817 /** initializes variable data structure for solving */
2818 void SCIPvarInitSolve(
2819  SCIP_VAR* var /**< problem variable */
2820  )
2821 {
2822  assert(var != NULL);
2823 
2825  var->conflictlbcount = 0;
2826  var->conflictubcount = 0;
2827 }
2828 
2829 /** outputs the given bounds into the file stream */
2830 static
2831 void printBounds(
2832  SCIP_SET* set, /**< global SCIP settings */
2833  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2834  FILE* file, /**< output file (or NULL for standard output) */
2835  SCIP_Real lb, /**< lower bound */
2836  SCIP_Real ub, /**< upper bound */
2837  const char* name /**< bound type name */
2838  )
2839 {
2840  assert(set != NULL);
2841 
2842  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2843  if( SCIPsetIsInfinity(set, lb) )
2844  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2845  else if( SCIPsetIsInfinity(set, -lb) )
2846  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2847  else
2848  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2849  if( SCIPsetIsInfinity(set, ub) )
2850  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2851  else if( SCIPsetIsInfinity(set, -ub) )
2852  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2853  else
2854  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2855 }
2856 
2857 /** prints hole list to file stream */
2858 static
2859 void printHolelist(
2860  SCIP_SET* set, /**< global SCIP settings */
2861  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2862  FILE* file, /**< output file (or NULL for standard output) */
2863  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2864  const char* name /**< hole type name */
2865  )
2866 { /*lint --e{715}*/
2867  SCIP_Real left;
2868  SCIP_Real right;
2869 
2870  if( holelist == NULL )
2871  return;
2872 
2873  left = SCIPholelistGetLeft(holelist);
2874  right = SCIPholelistGetRight(holelist);
2875 
2876  /* display first hole */
2877  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2878  holelist = SCIPholelistGetNext(holelist);
2879 
2880  while(holelist != NULL )
2881  {
2882  left = SCIPholelistGetLeft(holelist);
2883  right = SCIPholelistGetRight(holelist);
2884 
2885  /* display hole */
2886  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2887 
2888  /* get next hole */
2889  holelist = SCIPholelistGetNext(holelist);
2890  }
2891 }
2892 
2893 /** outputs variable information into file stream */
2895  SCIP_VAR* var, /**< problem variable */
2896  SCIP_SET* set, /**< global SCIP settings */
2897  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2898  FILE* file /**< output file (or NULL for standard output) */
2899  )
2900 {
2901  SCIP_HOLELIST* holelist;
2902  SCIP_Real lb;
2903  SCIP_Real ub;
2904  int i;
2905 
2906  assert(var != NULL);
2907  assert(var->scip == set->scip);
2908 
2909  /* type of variable */
2910  switch( SCIPvarGetType(var) )
2911  {
2912  case SCIP_VARTYPE_BINARY:
2913  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2914  break;
2915  case SCIP_VARTYPE_INTEGER:
2916  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2917  break;
2918  case SCIP_VARTYPE_IMPLINT:
2919  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2920  break;
2922  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2923  break;
2924  default:
2925  SCIPerrorMessage("unknown variable type\n");
2926  SCIPABORT();
2927  return SCIP_ERROR; /*lint !e527*/
2928  }
2929 
2930  /* name */
2931  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2932 
2933  /* objective value */
2934  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2935 
2936  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2937  if( !SCIPvarIsTransformed(var) )
2938  {
2939  /* output original bound */
2940  lb = SCIPvarGetLbOriginal(var);
2941  ub = SCIPvarGetUbOriginal(var);
2942  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2943 
2944  /* output lazy bound */
2945  lb = SCIPvarGetLbLazy(var);
2946  ub = SCIPvarGetUbLazy(var);
2947 
2948  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2949  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2950  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2951 
2952  holelist = SCIPvarGetHolelistOriginal(var);
2953  printHolelist(set, messagehdlr, file, holelist, "original holes");
2954  }
2955  else
2956  {
2957  /* output global bound */
2958  lb = SCIPvarGetLbGlobal(var);
2959  ub = SCIPvarGetUbGlobal(var);
2960  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2961 
2962  /* output local bound */
2963  lb = SCIPvarGetLbLocal(var);
2964  ub = SCIPvarGetUbLocal(var);
2965  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2966 
2967  /* output lazy bound */
2968  lb = SCIPvarGetLbLazy(var);
2969  ub = SCIPvarGetUbLazy(var);
2970 
2971  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2972  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2973  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2974 
2975  /* global hole list */
2976  holelist = SCIPvarGetHolelistGlobal(var);
2977  printHolelist(set, messagehdlr, file, holelist, "global holes");
2978 
2979  /* local hole list */
2980  holelist = SCIPvarGetHolelistLocal(var);
2981  printHolelist(set, messagehdlr, file, holelist, "local holes");
2982  }
2983 
2984  /* fixings and aggregations */
2985  switch( SCIPvarGetStatus(var) )
2986  {
2988  case SCIP_VARSTATUS_LOOSE:
2989  case SCIP_VARSTATUS_COLUMN:
2990  break;
2991 
2992  case SCIP_VARSTATUS_FIXED:
2993  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
2994  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
2995  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
2996  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
2997  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
2998  else
2999  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3000  break;
3001 
3003  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3004  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3005  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3006  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3007  break;
3008 
3010  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3011  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3012  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3013  for( i = 0; i < var->data.multaggr.nvars; ++i )
3014  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3015  break;
3016 
3018  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3019  break;
3020 
3021  default:
3022  SCIPerrorMessage("unknown variable status\n");
3023  SCIPABORT();
3024  return SCIP_ERROR; /*lint !e527*/
3025  }
3026 
3027  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3028 
3029  return SCIP_OKAY;
3030 }
3031 
3032 /** issues a VARUNLOCKED event on the given variable */
3033 static
3035  SCIP_VAR* var, /**< problem variable to change */
3036  BMS_BLKMEM* blkmem, /**< block memory */
3037  SCIP_SET* set, /**< global SCIP settings */
3038  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3039  )
3040 {
3041  SCIP_EVENT* event;
3042 
3043  assert(var != NULL);
3044  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3045  assert(var->scip == set->scip);
3046 
3047  /* issue VARUNLOCKED event on variable */
3048  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3049  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3050 
3051  return SCIP_OKAY;
3052 }
3053 
3054 /** modifies lock numbers for rounding */
3056  SCIP_VAR* var, /**< problem variable */
3057  BMS_BLKMEM* blkmem, /**< block memory */
3058  SCIP_SET* set, /**< global SCIP settings */
3059  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3060  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3061  int addnlocksdown, /**< increase in number of rounding down locks */
3062  int addnlocksup /**< increase in number of rounding up locks */
3063  )
3064 {
3065  SCIP_VAR* lockvar;
3066 
3067  assert(var != NULL);
3068  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3069  assert(var->nlocksup[locktype] >= 0);
3070  assert(var->nlocksdown[locktype] >= 0);
3071  assert(var->scip == set->scip);
3072 
3073  if( addnlocksdown == 0 && addnlocksup == 0 )
3074  return SCIP_OKAY;
3075 
3076 #ifdef SCIP_DEBUG
3077  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3078  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3079 #endif
3080 
3081  lockvar = var;
3082 
3083  while( TRUE ) /*lint !e716 */
3084  {
3085  assert(lockvar != NULL);
3086 
3087  switch( SCIPvarGetStatus(lockvar) )
3088  {
3090  if( lockvar->data.original.transvar != NULL )
3091  {
3092  lockvar = lockvar->data.original.transvar;
3093  break;
3094  }
3095  else
3096  {
3097  lockvar->nlocksdown[locktype] += addnlocksdown;
3098  lockvar->nlocksup[locktype] += addnlocksup;
3099 
3100  assert(lockvar->nlocksdown[locktype] >= 0);
3101  assert(lockvar->nlocksup[locktype] >= 0);
3102 
3103  return SCIP_OKAY;
3104  }
3105  case SCIP_VARSTATUS_LOOSE:
3106  case SCIP_VARSTATUS_COLUMN:
3107  case SCIP_VARSTATUS_FIXED:
3108  lockvar->nlocksdown[locktype] += addnlocksdown;
3109  lockvar->nlocksup[locktype] += addnlocksup;
3110 
3111  assert(lockvar->nlocksdown[locktype] >= 0);
3112  assert(lockvar->nlocksup[locktype] >= 0);
3113 
3114  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3115  && lockvar->nlocksup[locktype] <= 1 )
3116  {
3117  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3118  }
3119 
3120  return SCIP_OKAY;
3122  if( lockvar->data.aggregate.scalar < 0.0 )
3123  {
3124  int tmp = addnlocksup;
3125 
3126  addnlocksup = addnlocksdown;
3127  addnlocksdown = tmp;
3128  }
3129 
3130  lockvar = lockvar->data.aggregate.var;
3131  break;
3133  {
3134  int v;
3135 
3136  assert(!lockvar->donotmultaggr);
3137 
3138  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3139  {
3140  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3141  {
3142  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3143  addnlocksup) );
3144  }
3145  else
3146  {
3147  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3148  addnlocksdown) );
3149  }
3150  }
3151  return SCIP_OKAY;
3152  }
3154  {
3155  int tmp = addnlocksup;
3156 
3157  assert(lockvar->negatedvar != NULL);
3158  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3159  assert(lockvar->negatedvar->negatedvar == lockvar);
3160 
3161  addnlocksup = addnlocksdown;
3162  addnlocksdown = tmp;
3163 
3164  lockvar = lockvar->negatedvar;
3165  break;
3166  }
3167  default:
3168  SCIPerrorMessage("unknown variable status\n");
3169  return SCIP_INVALIDDATA;
3170  }
3171  }
3172 }
3173 
3174 /** gets number of locks for rounding down of a special type */
3176  SCIP_VAR* var, /**< problem variable */
3177  SCIP_LOCKTYPE locktype /**< type of variable locks */
3178  )
3179 {
3180  int nlocks;
3181  int i;
3182 
3183  assert(var != NULL);
3184  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3185  assert(var->nlocksdown[locktype] >= 0);
3186 
3187  switch( SCIPvarGetStatus(var) )
3188  {
3190  if( var->data.original.transvar != NULL )
3191  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3192  else
3193  return var->nlocksdown[locktype];
3194 
3195  case SCIP_VARSTATUS_LOOSE:
3196  case SCIP_VARSTATUS_COLUMN:
3197  case SCIP_VARSTATUS_FIXED:
3198  return var->nlocksdown[locktype];
3199 
3201  if( var->data.aggregate.scalar > 0.0 )
3202  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3203  else
3204  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3205 
3207  assert(!var->donotmultaggr);
3208  nlocks = 0;
3209  for( i = 0; i < var->data.multaggr.nvars; ++i )
3210  {
3211  if( var->data.multaggr.scalars[i] > 0.0 )
3212  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3213  else
3214  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3215  }
3216  return nlocks;
3217 
3219  assert(var->negatedvar != NULL);
3221  assert(var->negatedvar->negatedvar == var);
3222  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3223 
3224  default:
3225  SCIPerrorMessage("unknown variable status\n");
3226  SCIPABORT();
3227  return INT_MAX; /*lint !e527*/
3228  }
3229 }
3230 
3231 /** gets number of locks for rounding up of a special type */
3233  SCIP_VAR* var, /**< problem variable */
3234  SCIP_LOCKTYPE locktype /**< type of variable locks */
3235  )
3236 {
3237  int nlocks;
3238  int i;
3239 
3240  assert(var != NULL);
3241  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3242  assert(var->nlocksup[locktype] >= 0);
3243 
3244  switch( SCIPvarGetStatus(var) )
3245  {
3247  if( var->data.original.transvar != NULL )
3248  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3249  else
3250  return var->nlocksup[locktype];
3251 
3252  case SCIP_VARSTATUS_LOOSE:
3253  case SCIP_VARSTATUS_COLUMN:
3254  case SCIP_VARSTATUS_FIXED:
3255  return var->nlocksup[locktype];
3256 
3258  if( var->data.aggregate.scalar > 0.0 )
3259  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3260  else
3261  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3262 
3264  assert(!var->donotmultaggr);
3265  nlocks = 0;
3266  for( i = 0; i < var->data.multaggr.nvars; ++i )
3267  {
3268  if( var->data.multaggr.scalars[i] > 0.0 )
3269  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3270  else
3271  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3272  }
3273  return nlocks;
3274 
3276  assert(var->negatedvar != NULL);
3278  assert(var->negatedvar->negatedvar == var);
3279  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3280 
3281  default:
3282  SCIPerrorMessage("unknown variable status\n");
3283  SCIPABORT();
3284  return INT_MAX; /*lint !e527*/
3285  }
3286 }
3287 
3288 /** gets number of locks for rounding down
3289  *
3290  * @note This method will always return variable locks of type model
3291  *
3292  * @note It is recommented to use SCIPvarGetNLocksDownType()
3293  */
3295  SCIP_VAR* var /**< problem variable */
3296  )
3297 {
3299 }
3300 
3301 /** gets number of locks for rounding up
3302  *
3303  * @note This method will always return variable locks of type model
3304  *
3305  * @note It is recommented to use SCIPvarGetNLocksUpType()
3306  */
3307 int SCIPvarGetNLocksUp(
3308  SCIP_VAR* var /**< problem variable */
3309  )
3310 {
3312 }
3313 
3314 /** is it possible, to round variable down and stay feasible?
3315  *
3316  * @note This method will always check w.r.t variable locks of type model
3317  */
3319  SCIP_VAR* var /**< problem variable */
3320  )
3321 {
3322  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3323 }
3324 
3325 /** is it possible, to round variable up and stay feasible?
3326  *
3327  * @note This method will always check w.r.t. variable locks of type model
3328  */
3330  SCIP_VAR* var /**< problem variable */
3331  )
3332 {
3333  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3334 }
3335 
3336 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3337  * a new transformed variable for this variable is created
3338  */
3340  SCIP_VAR* origvar, /**< original problem variable */
3341  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3342  SCIP_SET* set, /**< global SCIP settings */
3343  SCIP_STAT* stat, /**< problem statistics */
3344  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3345  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3346  )
3347 {
3348  char name[SCIP_MAXSTRLEN];
3349 
3350  assert(origvar != NULL);
3351  assert(origvar->scip == set->scip);
3352  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3353  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3354  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3355  assert(origvar->vlbs == NULL);
3356  assert(origvar->vubs == NULL);
3357  assert(transvar != NULL);
3358 
3359  /* check if variable is already transformed */
3360  if( origvar->data.original.transvar != NULL )
3361  {
3362  *transvar = origvar->data.original.transvar;
3363  SCIPvarCapture(*transvar);
3364  }
3365  else
3366  {
3367  int i;
3368 
3369  /* create transformed variable */
3370  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3371  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3372  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3373  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3374  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3375 
3376  /* copy the branch factor and priority */
3377  (*transvar)->branchfactor = origvar->branchfactor;
3378  (*transvar)->branchpriority = origvar->branchpriority;
3379  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3380 
3381  /* duplicate hole lists */
3382  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3383  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3384 
3385  /* link original and transformed variable */
3386  origvar->data.original.transvar = *transvar;
3387  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3388 
3389  /* copy rounding locks */
3390  for( i = 0; i < NLOCKTYPES; i++ )
3391  {
3392  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3393  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3394  assert((*transvar)->nlocksdown[i] >= 0);
3395  assert((*transvar)->nlocksup[i] >= 0);
3396  }
3397 
3398  /* copy doNotMultiaggr status */
3399  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3400 
3401  /* copy lazy bounds */
3402  (*transvar)->lazylb = origvar->lazylb;
3403  (*transvar)->lazyub = origvar->lazyub;
3404 
3405  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3406  * when original variable was created
3407  */
3408  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3409 
3410  /* transform user data */
3411  if( origvar->vartrans != NULL )
3412  {
3413  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3414  }
3415  else
3416  (*transvar)->vardata = origvar->vardata;
3417  }
3418 
3419  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3420 
3421  return SCIP_OKAY;
3422 }
3423 
3424 /** gets corresponding transformed variable of an original or negated original variable */
3426  SCIP_VAR* origvar, /**< original problem variable */
3427  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3428  SCIP_SET* set, /**< global SCIP settings */
3429  SCIP_STAT* stat, /**< problem statistics */
3430  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3431  )
3432 {
3433  assert(origvar != NULL);
3435  assert(origvar->scip == set->scip);
3436 
3437  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3438  {
3439  assert(origvar->negatedvar != NULL);
3441 
3442  if( origvar->negatedvar->data.original.transvar == NULL )
3443  *transvar = NULL;
3444  else
3445  {
3446  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3447  }
3448  }
3449  else
3450  *transvar = origvar->data.original.transvar;
3451 
3452  return SCIP_OKAY;
3453 }
3454 
3455 /** converts loose transformed variable into column variable, creates LP column */
3457  SCIP_VAR* var, /**< problem variable */
3458  BMS_BLKMEM* blkmem, /**< block memory */
3459  SCIP_SET* set, /**< global SCIP settings */
3460  SCIP_STAT* stat, /**< problem statistics */
3461  SCIP_PROB* prob, /**< problem data */
3462  SCIP_LP* lp /**< current LP data */
3463  )
3464 {
3465  assert(var != NULL);
3466  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3467  assert(var->scip == set->scip);
3468 
3469  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3470 
3471  /* switch variable status */
3472  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3473 
3474  /* create column of variable */
3475  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3476 
3477  if( var->probindex != -1 )
3478  {
3479  /* inform problem about the variable's status change */
3480  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3481 
3482  /* inform LP, that problem variable is now a column variable and no longer loose */
3483  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3484  }
3485 
3486  return SCIP_OKAY;
3487 }
3488 
3489 /** converts column transformed variable back into loose variable, frees LP column */
3491  SCIP_VAR* var, /**< problem variable */
3492  BMS_BLKMEM* blkmem, /**< block memory */
3493  SCIP_SET* set, /**< global SCIP settings */
3494  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3495  SCIP_PROB* prob, /**< problem data */
3496  SCIP_LP* lp /**< current LP data */
3497  )
3498 {
3499  assert(var != NULL);
3500  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3501  assert(var->scip == set->scip);
3502  assert(var->data.col != NULL);
3503  assert(var->data.col->lppos == -1);
3504  assert(var->data.col->lpipos == -1);
3505 
3506  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3507 
3508  /* free column of variable */
3509  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3510 
3511  /* switch variable status */
3512  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3513 
3514  if( var->probindex != -1 )
3515  {
3516  /* inform problem about the variable's status change */
3517  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3518 
3519  /* inform LP, that problem variable is now a loose variable and no longer a column */
3520  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3521  }
3522 
3523  return SCIP_OKAY;
3524 }
3525 
3526 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3527  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3528  * are not informed about a fixing of an active variable they are pointing to
3529  */
3530 static
3532  SCIP_VAR* var, /**< problem variable to change */
3533  BMS_BLKMEM* blkmem, /**< block memory */
3534  SCIP_SET* set, /**< global SCIP settings */
3535  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3536  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3537  * multi-aggregation(2)
3538  */
3539  )
3540 {
3541  SCIP_EVENT* event;
3542  SCIP_VARSTATUS varstatus;
3543  int i;
3544 
3545  assert(var != NULL);
3546  assert(var->scip == set->scip);
3547  assert(0 <= fixeventtype && fixeventtype <= 2);
3548 
3549  /* issue VARFIXED event on variable */
3550  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3551  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3552 
3553 #ifndef NDEBUG
3554  for( i = var->nparentvars -1; i >= 0; --i )
3555  {
3557  }
3558 #endif
3559 
3560  switch( fixeventtype )
3561  {
3562  case 0:
3563  /* process all parents of a fixed variable */
3564  for( i = var->nparentvars - 1; i >= 0; --i )
3565  {
3566  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3567 
3568  assert(varstatus != SCIP_VARSTATUS_FIXED);
3569 
3570  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3571  * one
3572  */
3573  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3574  {
3575  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3576  }
3577  }
3578  break;
3579  case 1:
3580  /* process all parents of a aggregated variable */
3581  for( i = var->nparentvars - 1; i >= 0; --i )
3582  {
3583  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3584 
3585  assert(varstatus != SCIP_VARSTATUS_FIXED);
3586 
3587  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3588  * issued(, except the original one)
3589  *
3590  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3591  * yet issued
3592  */
3593  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3594  continue;
3595 
3596  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3597  {
3598  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3599  }
3600  }
3601  break;
3602  case 2:
3603  /* process all parents of a aggregated variable */
3604  for( i = var->nparentvars - 1; i >= 0; --i )
3605  {
3606  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3607 
3608  assert(varstatus != SCIP_VARSTATUS_FIXED);
3609 
3610  /* issue event on all parent variables except the original one */
3611  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3612  {
3613  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3614  }
3615  }
3616  break;
3617  default:
3618  SCIPerrorMessage("unknown variable fixation event origin\n");
3619  return SCIP_INVALIDDATA;
3620  }
3621 
3622  return SCIP_OKAY;
3623 }
3624 
3625 /** converts variable into fixed variable */
3627  SCIP_VAR* var, /**< problem variable */
3628  BMS_BLKMEM* blkmem, /**< block memory */
3629  SCIP_SET* set, /**< global SCIP settings */
3630  SCIP_STAT* stat, /**< problem statistics */
3631  SCIP_PROB* transprob, /**< tranformed problem data */
3632  SCIP_PROB* origprob, /**< original problem data */
3633  SCIP_PRIMAL* primal, /**< primal data */
3634  SCIP_TREE* tree, /**< branch and bound tree */
3635  SCIP_REOPT* reopt, /**< reoptimization data structure */
3636  SCIP_LP* lp, /**< current LP data */
3637  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3638  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3639  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3640  SCIP_Real fixedval, /**< value to fix variable at */
3641  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3642  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3643  )
3644 {
3645  SCIP_Real obj;
3646  SCIP_Real childfixedval;
3647 
3648  assert(var != NULL);
3649  assert(var->scip == set->scip);
3650  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3651  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3652  assert(infeasible != NULL);
3653  assert(fixed != NULL);
3654 
3655  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3656 
3657  *infeasible = FALSE;
3658  *fixed = FALSE;
3659 
3661  {
3662  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3663  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3664  return SCIP_OKAY;
3665  }
3666  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3667  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3668  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3669  {
3670  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3671  *infeasible = TRUE;
3672  return SCIP_OKAY;
3673  }
3674 
3675  switch( SCIPvarGetStatus(var) )
3676  {
3678  if( var->data.original.transvar == NULL )
3679  {
3680  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3681  return SCIP_INVALIDDATA;
3682  }
3683  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3684  lp, branchcand, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3685  break;
3686 
3687  case SCIP_VARSTATUS_LOOSE:
3688  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3689 
3690  /* set the fixed variable's objective value to 0.0 */
3691  obj = var->obj;
3692  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3693 
3694  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3695  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3696  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3697  * objective of this variable is set to zero
3698  */
3699  SCIPlpDecNLoosevars(lp);
3700 
3701  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3702  holelistFree(&var->glbdom.holelist, blkmem);
3703  holelistFree(&var->locdom.holelist, blkmem);
3704  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3705  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3706 
3707  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3708  var->glbdom.lb = fixedval;
3709  var->glbdom.ub = fixedval;
3710  var->locdom.lb = fixedval;
3711  var->locdom.ub = fixedval;
3712 
3713  /* delete implications and variable bounds information */
3714  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3715  assert(var->vlbs == NULL);
3716  assert(var->vubs == NULL);
3717  assert(var->implics == NULL);
3718  assert(var->cliquelist == NULL);
3719 
3720  /* clear the history of the variable */
3721  SCIPhistoryReset(var->history);
3723 
3724  /* convert variable into fixed variable */
3725  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3726 
3727  /* inform problem about the variable's status change */
3728  if( var->probindex != -1 )
3729  {
3730  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3731  }
3732 
3733  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3734  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
3735 
3736  /* issue VARFIXED event */
3737  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3738 
3739  *fixed = TRUE;
3740  break;
3741 
3742  case SCIP_VARSTATUS_COLUMN:
3743  SCIPerrorMessage("cannot fix a column variable\n");
3744  return SCIP_INVALIDDATA;
3745 
3746  case SCIP_VARSTATUS_FIXED:
3747  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3748  SCIPABORT(); /* case is already handled in earlier if condition */
3749  return SCIP_INVALIDDATA; /*lint !e527*/
3750 
3752  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3753  assert(SCIPsetIsZero(set, var->obj));
3754  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3755  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3756  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3757  else
3758  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3759  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3760  branchcand, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3761  break;
3762 
3764  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3765  SCIPABORT();
3766  return SCIP_INVALIDDATA; /*lint !e527*/
3767 
3769  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3770  assert(SCIPsetIsZero(set, var->obj));
3771  assert(var->negatedvar != NULL);
3773  assert(var->negatedvar->negatedvar == var);
3774  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3775  branchcand, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3776  break;
3777 
3778  default:
3779  SCIPerrorMessage("unknown variable status\n");
3780  return SCIP_INVALIDDATA;
3781  }
3782 
3783  return SCIP_OKAY;
3784 }
3785 
3786 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3787  *
3788  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3789  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3790  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3791  *
3792  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3793  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3794  */
3796  SCIP_SET* set, /**< global SCIP settings */
3797  SCIP_VAR** vars, /**< variable array to get active variables */
3798  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3799  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3800  int varssize, /**< available slots in vars and scalars array */
3801  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3802  int* requiredsize, /**< pointer to store the required array size for the active variables */
3803  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3804  )
3805 {
3806  SCIP_VAR** activevars;
3807  SCIP_Real* activescalars;
3808  int nactivevars;
3809  SCIP_Real activeconstant;
3810  SCIP_Bool activeconstantinf;
3811  int activevarssize;
3812 
3813  SCIP_VAR* var;
3814  SCIP_Real scalar;
3815  int v;
3816  int k;
3817 
3818  SCIP_VAR** tmpvars;
3819  SCIP_VAR** multvars;
3820  SCIP_Real* tmpscalars;
3821  SCIP_Real* multscalars;
3822  int tmpvarssize;
3823  int ntmpvars;
3824  int nmultvars;
3825 
3826  SCIP_VAR* multvar;
3827  SCIP_Real multscalar;
3828  SCIP_Real multconstant;
3829  int pos;
3830 
3831  int noldtmpvars;
3832 
3833  SCIP_VAR** tmpvars2;
3834  SCIP_Real* tmpscalars2;
3835  int tmpvarssize2;
3836  int ntmpvars2;
3837 
3838  SCIP_Bool sortagain = FALSE;
3839 
3840  assert(set != NULL);
3841  assert(nvars != NULL);
3842  assert(scalars != NULL || *nvars == 0);
3843  assert(constant != NULL);
3844  assert(requiredsize != NULL);
3845  assert(*nvars <= varssize);
3846 
3847  *requiredsize = 0;
3848 
3849  if( *nvars == 0 )
3850  return SCIP_OKAY;
3851 
3852  assert(vars != NULL);
3853 
3854  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3855  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3856  {
3857  *requiredsize = 1;
3858 
3859  return SCIP_OKAY;
3860  }
3861 
3862  nactivevars = 0;
3863  activeconstant = 0.0;
3864  activeconstantinf = FALSE;
3865  activevarssize = (*nvars) * 2;
3866  ntmpvars = *nvars;
3867  tmpvarssize = *nvars;
3868 
3869  tmpvarssize2 = 1;
3870 
3871  /* allocate temporary memory */
3872  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3873  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3874  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3875  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3876  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3877  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3878 
3879  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3880  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3881  */
3882  for( v = ntmpvars - 1; v >= 0; --v )
3883  {
3884  var = tmpvars[v];
3885  scalar = tmpscalars[v];
3886 
3887  assert(var != NULL);
3888  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3889  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3890  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3891  */
3892  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3893  assert(var != NULL);
3894 
3895  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3896  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3897 
3898  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3899 
3900  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3901  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3904 
3905  tmpvars[v] = var;
3906  tmpscalars[v] = scalar;
3907  }
3908  noldtmpvars = ntmpvars;
3909 
3910  /* sort all variables to combine equal variables easily */
3911  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
3912  ntmpvars = 0;
3913  for( v = 1; v < noldtmpvars; ++v )
3914  {
3915  /* combine same variables */
3916  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
3917  {
3918  tmpscalars[ntmpvars] += tmpscalars[v];
3919  }
3920  else
3921  {
3922  ++ntmpvars;
3923  if( v > ntmpvars )
3924  {
3925  tmpscalars[ntmpvars] = tmpscalars[v];
3926  tmpvars[ntmpvars] = tmpvars[v];
3927  }
3928  }
3929  }
3930  ++ntmpvars;
3931 
3932 #ifdef SCIP_MORE_DEBUG
3933  for( v = 1; v < ntmpvars; ++v )
3934  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
3935 #endif
3936 
3937  /* collect for each variable the representation in active variables */
3938  while( ntmpvars >= 1 )
3939  {
3940  --ntmpvars;
3941  ntmpvars2 = 0;
3942  var = tmpvars[ntmpvars];
3943  scalar = tmpscalars[ntmpvars];
3944 
3945  assert(var != NULL);
3946 
3947  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3948  if( scalar == 0.0 )
3949  continue;
3950 
3951  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3952  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3955 
3956  switch( SCIPvarGetStatus(var) )
3957  {
3958  case SCIP_VARSTATUS_LOOSE:
3959  case SCIP_VARSTATUS_COLUMN:
3960  /* x = a*y + c */
3961  if( nactivevars >= activevarssize )
3962  {
3963  activevarssize *= 2;
3964  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3965  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3966  assert(nactivevars < activevarssize);
3967  }
3968  activevars[nactivevars] = var;
3969  activescalars[nactivevars] = scalar;
3970  nactivevars++;
3971  break;
3972 
3974  /* x = a_1*y_1 + ... + a_n*y_n + c */
3975  nmultvars = var->data.multaggr.nvars;
3976  multvars = var->data.multaggr.vars;
3977  multscalars = var->data.multaggr.scalars;
3978  sortagain = TRUE;
3979 
3980  if( nmultvars + ntmpvars > tmpvarssize )
3981  {
3982  while( nmultvars + ntmpvars > tmpvarssize )
3983  tmpvarssize *= 2;
3984  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3985  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3986  assert(nmultvars + ntmpvars <= tmpvarssize);
3987  }
3988 
3989  if( nmultvars > tmpvarssize2 )
3990  {
3991  while( nmultvars > tmpvarssize2 )
3992  tmpvarssize2 *= 2;
3993  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3994  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3995  assert(nmultvars <= tmpvarssize2);
3996  }
3997 
3998  --nmultvars;
3999 
4000  for( ; nmultvars >= 0; --nmultvars )
4001  {
4002  multvar = multvars[nmultvars];
4003  multscalar = multscalars[nmultvars];
4004  multconstant = 0;
4005 
4006  assert(multvar != NULL);
4007  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4008  assert(multvar != NULL);
4009 
4010  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4011  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4014 
4015  if( !activeconstantinf )
4016  {
4017  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4018 
4019  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4020  {
4021  assert(scalar != 0.0);
4022  if( scalar * multconstant > 0.0 )
4023  {
4024  activeconstant = SCIPsetInfinity(set);
4025  activeconstantinf = TRUE;
4026  }
4027  else
4028  {
4029  activeconstant = -SCIPsetInfinity(set);
4030  activeconstantinf = TRUE;
4031  }
4032  }
4033  else
4034  activeconstant += scalar * multconstant;
4035  }
4036 #ifndef NDEBUG
4037  else
4038  {
4039  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4040  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4041  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4042  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4043  }
4044 #endif
4045 
4046  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4047  {
4048  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4049  tmpscalars[pos] += scalar * multscalar;
4050  }
4051  else
4052  {
4053  tmpvars2[ntmpvars2] = multvar;
4054  tmpscalars2[ntmpvars2] = scalar * multscalar;
4055  ++(ntmpvars2);
4056  assert(ntmpvars2 <= tmpvarssize2);
4057  }
4058  }
4059 
4060  if( ntmpvars2 > 0 )
4061  {
4062  /* sort all variables to combine equal variables easily */
4063  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4064  pos = 0;
4065  for( v = 1; v < ntmpvars2; ++v )
4066  {
4067  /* combine same variables */
4068  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4069  {
4070  tmpscalars2[pos] += tmpscalars2[v];
4071  }
4072  else
4073  {
4074  ++pos;
4075  if( v > pos )
4076  {
4077  tmpscalars2[pos] = tmpscalars2[v];
4078  tmpvars2[pos] = tmpvars2[v];
4079  }
4080  }
4081  }
4082  ntmpvars2 = pos + 1;
4083 #ifdef SCIP_MORE_DEBUG
4084  for( v = 1; v < ntmpvars2; ++v )
4085  {
4086  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4087  }
4088  for( v = 1; v < ntmpvars; ++v )
4089  {
4090  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4091  }
4092 #endif
4093  v = ntmpvars - 1;
4094  k = ntmpvars2 - 1;
4095  pos = ntmpvars + ntmpvars2 - 1;
4096  ntmpvars += ntmpvars2;
4097 
4098  while( v >= 0 && k >= 0 )
4099  {
4100  assert(pos >= 0);
4101  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4102  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4103  {
4104  tmpvars[pos] = tmpvars[v];
4105  tmpscalars[pos] = tmpscalars[v];
4106  --v;
4107  }
4108  else
4109  {
4110  tmpvars[pos] = tmpvars2[k];
4111  tmpscalars[pos] = tmpscalars2[k];
4112  --k;
4113  }
4114  --pos;
4115  assert(pos >= 0);
4116  }
4117  while( v >= 0 )
4118  {
4119  assert(pos >= 0);
4120  tmpvars[pos] = tmpvars[v];
4121  tmpscalars[pos] = tmpscalars[v];
4122  --v;
4123  --pos;
4124  }
4125  while( k >= 0 )
4126  {
4127  assert(pos >= 0);
4128  tmpvars[pos] = tmpvars2[k];
4129  tmpscalars[pos] = tmpscalars2[k];
4130  --k;
4131  --pos;
4132  }
4133  }
4134 #ifdef SCIP_MORE_DEBUG
4135  for( v = 1; v < ntmpvars; ++v )
4136  {
4137  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4138  }
4139 #endif
4140 
4141  if( !activeconstantinf )
4142  {
4143  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4144 
4145  multconstant = SCIPvarGetMultaggrConstant(var);
4146 
4147  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4148  {
4149  assert(scalar != 0.0);
4150  if( scalar * multconstant > 0.0 )
4151  {
4152  activeconstant = SCIPsetInfinity(set);
4153  activeconstantinf = TRUE;
4154  }
4155  else
4156  {
4157  activeconstant = -SCIPsetInfinity(set);
4158  activeconstantinf = TRUE;
4159  }
4160  }
4161  else
4162  activeconstant += scalar * multconstant;
4163  }
4164 #ifndef NDEBUG
4165  else
4166  {
4167  multconstant = SCIPvarGetMultaggrConstant(var);
4168  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4169  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4170  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4171  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4172  }
4173 #endif
4174  break;
4175 
4176  case SCIP_VARSTATUS_FIXED:
4180  default:
4181  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4182  * fixed variables and is handled already
4183  */
4184  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4185  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4186  }
4187  }
4188 
4189  if( mergemultiples )
4190  {
4191  if( sortagain )
4192  {
4193  /* sort variable and scalar array by variable index */
4194  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4195 
4196  /* eliminate duplicates and count required size */
4197  v = nactivevars - 1;
4198  while( v > 0 )
4199  {
4200  /* combine both variable since they are the same */
4201  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4202  {
4203  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4204  {
4205  activescalars[v - 1] += activescalars[v];
4206  --nactivevars;
4207  activevars[v] = activevars[nactivevars];
4208  activescalars[v] = activescalars[nactivevars];
4209  }
4210  else
4211  {
4212  --nactivevars;
4213  activevars[v] = activevars[nactivevars];
4214  activescalars[v] = activescalars[nactivevars];
4215  --nactivevars;
4216  --v;
4217  activevars[v] = activevars[nactivevars];
4218  activescalars[v] = activescalars[nactivevars];
4219  }
4220  }
4221  --v;
4222  }
4223  }
4224  /* the variables were added in reverse order, we revert the order now;
4225  * this should not be necessary, but not doing this changes the behavior sometimes
4226  */
4227  else
4228  {
4229  SCIP_VAR* tmpvar;
4230  SCIP_Real tmpscalar;
4231 
4232  for( v = 0; v < nactivevars / 2; ++v )
4233  {
4234  tmpvar = activevars[v];
4235  tmpscalar = activescalars[v];
4236  activevars[v] = activevars[nactivevars - 1 - v];
4237  activescalars[v] = activescalars[nactivevars - 1 - v];
4238  activevars[nactivevars - 1 - v] = tmpvar;
4239  activescalars[nactivevars - 1 - v] = tmpscalar;
4240  }
4241  }
4242  }
4243  *requiredsize = nactivevars;
4244 
4245  if( varssize >= *requiredsize )
4246  {
4247  assert(vars != NULL);
4248 
4249  *nvars = *requiredsize;
4250 
4251  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4252  {
4253  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4254  if( activeconstantinf )
4255  (*constant) = activeconstant;
4256  else
4257  (*constant) += activeconstant;
4258  }
4259 #ifndef NDEBUG
4260  else
4261  {
4262  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4263  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4264  }
4265 #endif
4266 
4267  /* copy active variable and scalar array to the given arrays */
4268  for( v = 0; v < *nvars; ++v )
4269  {
4270  vars[v] = activevars[v];
4271  scalars[v] = activescalars[v]; /*lint !e613*/
4272  }
4273  }
4274 
4275  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4276  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4277 
4278  SCIPsetFreeBufferArray(set, &tmpscalars);
4279  SCIPsetFreeBufferArray(set, &tmpvars);
4280  SCIPsetFreeBufferArray(set, &activescalars);
4281  SCIPsetFreeBufferArray(set, &activevars);
4282  SCIPsetFreeBufferArray(set, &tmpscalars2);
4283  SCIPsetFreeBufferArray(set, &tmpvars2);
4284 
4285  return SCIP_OKAY;
4286 }
4287 
4288 
4289 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4291  SCIP_VAR* var, /**< problem variable */
4292  BMS_BLKMEM* blkmem, /**< block memory */
4293  SCIP_SET* set /**< global SCIP settings */
4294  )
4295 {
4296  SCIP_Real multconstant;
4297  int multvarssize;
4298  int nmultvars;
4299  int multrequiredsize;
4300 
4301  assert( var != NULL );
4302  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4303  assert(var->scip == set->scip);
4304 
4305  multconstant = var->data.multaggr.constant;
4306  nmultvars = var->data.multaggr.nvars;
4307  multvarssize = var->data.multaggr.varssize;
4308 
4309  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4310 
4311  if( multrequiredsize > multvarssize )
4312  {
4313  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4314  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4315  multvarssize = multrequiredsize;
4316  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4317  assert( multrequiredsize <= multvarssize );
4318  }
4319  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4320  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4321  * may loose performance hereby, since aggregated variables are easier to handle.
4322  *
4323  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4324  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4325  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4326  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4327  *
4328  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4329  *
4330  * The same issue appears in the SCIPvarGetProbvar...() methods.
4331  */
4332 
4333  var->data.multaggr.constant = multconstant;
4334  var->data.multaggr.nvars = nmultvars;
4335  var->data.multaggr.varssize = multvarssize;
4336 
4337  return SCIP_OKAY;
4338 }
4339 
4340 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4341  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4342  * the history merge is reasonable
4343  *
4344  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4345  * this corrupts the variable pseudo costs
4346  * @note Apply with care; no internal checks are performed if the two variables should be merged
4347  */
4349  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4350  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4351  SCIP_STAT* stat /**< problem statistics */
4352  )
4353 {
4354  /* merge only the history of the current run into the target history */
4355  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4356 
4357  /* apply the changes also to the global history */
4358  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4359 }
4360 
4361 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4362  * history over several iterations
4363  */
4364 void SCIPvarSetHistory(
4365  SCIP_VAR* var, /**< variable */
4366  SCIP_HISTORY* history, /**< the history which is to set */
4367  SCIP_STAT* stat /**< problem statistics */
4368  )
4369 {
4370  /* merge only the history of the current run into the target history */
4371  SCIPhistoryUnite(var->history, history, FALSE);
4372 
4373  /* apply the changes also to the global history */
4374  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4375 }
4376 
4377 /** tightens the bounds of both variables in aggregation x = a*y + c */
4378 static
4380  SCIP_VAR* var, /**< problem variable */
4381  BMS_BLKMEM* blkmem, /**< block memory */
4382  SCIP_SET* set, /**< global SCIP settings */
4383  SCIP_STAT* stat, /**< problem statistics */
4384  SCIP_PROB* transprob, /**< tranformed problem data */
4385  SCIP_PROB* origprob, /**< original problem data */
4386  SCIP_PRIMAL* primal, /**< primal data */
4387  SCIP_TREE* tree, /**< branch and bound tree */
4388  SCIP_REOPT* reopt, /**< reoptimization data structure */
4389  SCIP_LP* lp, /**< current LP data */
4390  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4391  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4392  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4393  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4394  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4395  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4396  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4397  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4398  )
4399 {
4400  SCIP_Real varlb;
4401  SCIP_Real varub;
4402  SCIP_Real aggvarlb;
4403  SCIP_Real aggvarub;
4404  SCIP_Bool aggvarbdschanged;
4405 
4406  assert(var != NULL);
4407  assert(var->scip == set->scip);
4408  assert(aggvar != NULL);
4409  assert(!SCIPsetIsZero(set, scalar));
4410  assert(infeasible != NULL);
4411  assert(fixed != NULL);
4412 
4413  *infeasible = FALSE;
4414  *fixed = FALSE;
4415 
4416  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4417  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4418  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4419 
4420  /* loop as long additional changes may be found */
4421  do
4422  {
4423  aggvarbdschanged = FALSE;
4424 
4425  /* update the bounds of the aggregated variable x in x = a*y + c */
4426  if( scalar > 0.0 )
4427  {
4428  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4429  varlb = -SCIPsetInfinity(set);
4430  else
4431  varlb = aggvar->glbdom.lb * scalar + constant;
4432  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4433  varub = SCIPsetInfinity(set);
4434  else
4435  varub = aggvar->glbdom.ub * scalar + constant;
4436  }
4437  else
4438  {
4439  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4440  varub = SCIPsetInfinity(set);
4441  else
4442  varub = aggvar->glbdom.lb * scalar + constant;
4443  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4444  varlb = -SCIPsetInfinity(set);
4445  else
4446  varlb = aggvar->glbdom.ub * scalar + constant;
4447  }
4448  varlb = MAX(varlb, var->glbdom.lb);
4449  varub = MIN(varub, var->glbdom.ub);
4450  SCIPvarAdjustLb(var, set, &varlb);
4451  SCIPvarAdjustUb(var, set, &varub);
4452 
4453  /* check the new bounds */
4454  if( SCIPsetIsGT(set, varlb, varub) )
4455  {
4456  /* the aggregation is infeasible */
4457  *infeasible = TRUE;
4458  return SCIP_OKAY;
4459  }
4460  else if( SCIPsetIsEQ(set, varlb, varub) )
4461  {
4462  /* the aggregated variable is fixed -> fix both variables */
4463  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4464  eventqueue, cliquetable, varlb, infeasible, fixed) );
4465  if( !(*infeasible) )
4466  {
4467  SCIP_Bool aggfixed;
4468 
4469  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4470  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4471  assert(*fixed == aggfixed);
4472  }
4473  return SCIP_OKAY;
4474  }
4475  else
4476  {
4477  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4478  {
4479  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4480  }
4481  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4482  {
4483  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4484  }
4485 
4486  /* update the hole list of the aggregation variable */
4487  /**@todo update hole list of aggregation variable */
4488  }
4489 
4490  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4491  if( scalar > 0.0 )
4492  {
4493  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4494  aggvarlb = -SCIPsetInfinity(set);
4495  else
4496  aggvarlb = (var->glbdom.lb - constant) / scalar;
4497  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4498  aggvarub = SCIPsetInfinity(set);
4499  else
4500  aggvarub = (var->glbdom.ub - constant) / scalar;
4501  }
4502  else
4503  {
4504  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4505  aggvarub = SCIPsetInfinity(set);
4506  else
4507  aggvarub = (var->glbdom.lb - constant) / scalar;
4508  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4509  aggvarlb = -SCIPsetInfinity(set);
4510  else
4511  aggvarlb = (var->glbdom.ub - constant) / scalar;
4512  }
4513  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4514  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4515  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4516  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4517 
4518  /* check the new bounds */
4519  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4520  {
4521  /* the aggregation is infeasible */
4522  *infeasible = TRUE;
4523  return SCIP_OKAY;
4524  }
4525  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4526  {
4527  /* the aggregation variable is fixed -> fix both variables */
4528  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4529  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4530  if( !(*infeasible) )
4531  {
4532  SCIP_Bool varfixed;
4533 
4534  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4535  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4536  assert(*fixed == varfixed);
4537  }
4538  return SCIP_OKAY;
4539  }
4540  else
4541  {
4542  SCIP_Real oldbd;
4543  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4544  {
4545  oldbd = aggvar->glbdom.lb;
4546  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4547  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4548  }
4549  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4550  {
4551  oldbd = aggvar->glbdom.ub;
4552  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4553  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4554  }
4555 
4556  /* update the hole list of the aggregation variable */
4557  /**@todo update hole list of aggregation variable */
4558  }
4559  }
4560  while( aggvarbdschanged );
4561 
4562  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4563  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4564 
4565  return SCIP_OKAY;
4566 }
4567 
4568 /** converts loose variable into aggregated variable */
4570  SCIP_VAR* var, /**< loose problem variable */
4571  BMS_BLKMEM* blkmem, /**< block memory */
4572  SCIP_SET* set, /**< global SCIP settings */
4573  SCIP_STAT* stat, /**< problem statistics */
4574  SCIP_PROB* transprob, /**< tranformed problem data */
4575  SCIP_PROB* origprob, /**< original problem data */
4576  SCIP_PRIMAL* primal, /**< primal data */
4577  SCIP_TREE* tree, /**< branch and bound tree */
4578  SCIP_REOPT* reopt, /**< reoptimization data structure */
4579  SCIP_LP* lp, /**< current LP data */
4580  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4581  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4582  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4583  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4584  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4585  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4586  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4587  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4588  )
4589 {
4590  SCIP_VAR** vars;
4591  SCIP_Real* coefs;
4592  SCIP_Real* constants;
4593  SCIP_Real obj;
4594  SCIP_Real branchfactor;
4595  SCIP_Bool fixed;
4596  int branchpriority;
4597  int nlocksdown[NLOCKTYPES];
4598  int nlocksup[NLOCKTYPES];
4599  int nvbds;
4600  int i;
4601  int j;
4602 
4603  assert(var != NULL);
4604  assert(aggvar != NULL);
4605  assert(var->scip == set->scip);
4606  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4607  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4608  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4609  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4610  assert(infeasible != NULL);
4611  assert(aggregated != NULL);
4612 
4613  /* check aggregation on debugging solution */
4614  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4615 
4616  *infeasible = FALSE;
4617  *aggregated = FALSE;
4618 
4619  /* get active problem variable of aggregation variable */
4620  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4621 
4622  /* aggregation is a fixing, if the scalar is zero */
4623  if( SCIPsetIsZero(set, scalar) )
4624  {
4625  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4626  cliquetable, constant, infeasible, aggregated) );
4627  return SCIP_OKAY;
4628  }
4629 
4630  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4631  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4632  return SCIP_OKAY;
4633 
4634  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4635  * should be changed in the future
4636  */
4637  if( SCIPvarGetHolelistGlobal(var) != NULL )
4638  return SCIP_OKAY;
4639 
4640  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4641  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4642  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4643 
4644  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4645  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4646 
4647  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4648  if( var == aggvar )
4649  {
4650  if( SCIPsetIsEQ(set, scalar, 1.0) )
4651  *infeasible = !SCIPsetIsZero(set, constant);
4652  else
4653  {
4654  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4655  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4656  }
4657  return SCIP_OKAY;
4658  }
4659 
4660  /* tighten the bounds of aggregated and aggregation variable */
4661  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4662  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4663  if( *infeasible || fixed )
4664  {
4665  *aggregated = fixed;
4666  return SCIP_OKAY;
4667  }
4668 
4669  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4670  * aggregated variable
4671  */
4672  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4673  assert(var->cliquelist == NULL);
4674 
4675  /* set the aggregated variable's objective value to 0.0 */
4676  obj = var->obj;
4677  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4678 
4679  /* unlock all locks */
4680  for( i = 0; i < NLOCKTYPES; i++ )
4681  {
4682  nlocksdown[i] = var->nlocksdown[i];
4683  nlocksup[i] = var->nlocksup[i];
4684 
4685  var->nlocksdown[i] = 0;
4686  var->nlocksup[i] = 0;
4687  }
4688 
4689  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4690  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4691  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4692  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4693  {
4694  /* link both variables as negation pair */
4695  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4696  var->data.negate.constant = 1.0;
4697  var->negatedvar = aggvar;
4698  aggvar->negatedvar = var;
4699 
4700  /* copy doNotMultiaggr status */
4701  aggvar->donotmultaggr |= var->donotmultaggr;
4702 
4703  /* mark both variables to be non-deletable */
4705  SCIPvarMarkNotDeletable(aggvar);
4706  }
4707  else
4708  {
4709  /* convert variable into aggregated variable */
4710  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4711  var->data.aggregate.var = aggvar;
4712  var->data.aggregate.scalar = scalar;
4713  var->data.aggregate.constant = constant;
4714 
4715  /* copy doNotMultiaggr status */
4716  aggvar->donotmultaggr |= var->donotmultaggr;
4717 
4718  /* mark both variables to be non-deletable */
4720  SCIPvarMarkNotDeletable(aggvar);
4721  }
4722 
4723  /* make aggregated variable a parent of the aggregation variable */
4724  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4725 
4726  /* relock the variable, thus increasing the locks of the aggregation variable */
4727  for( i = 0; i < NLOCKTYPES; i++ )
4728  {
4729  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4730  }
4731 
4732  /* move the variable bounds to the aggregation variable:
4733  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4734  * - free the variable bounds data structures
4735  */
4736  if( var->vlbs != NULL )
4737  {
4738  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4739  vars = SCIPvboundsGetVars(var->vlbs);
4740  coefs = SCIPvboundsGetCoefs(var->vlbs);
4741  constants = SCIPvboundsGetConstants(var->vlbs);
4742  for( i = 0; i < nvbds && !(*infeasible); ++i )
4743  {
4744  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4745  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4746  }
4747  }
4748  if( var->vubs != NULL )
4749  {
4750  nvbds = SCIPvboundsGetNVbds(var->vubs);
4751  vars = SCIPvboundsGetVars(var->vubs);
4752  coefs = SCIPvboundsGetCoefs(var->vubs);
4753  constants = SCIPvboundsGetConstants(var->vubs);
4754  for( i = 0; i < nvbds && !(*infeasible); ++i )
4755  {
4756  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4757  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4758  }
4759  }
4760  SCIPvboundsFree(&var->vlbs, blkmem);
4761  SCIPvboundsFree(&var->vubs, blkmem);
4762 
4763  /* move the implications to the aggregation variable:
4764  * - add all implications again to the variable, thus adding it to the aggregation variable
4765  * - free the implications data structures
4766  */
4767  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4768  {
4769  assert(SCIPvarIsBinary(var));
4770  for( i = 0; i < 2; ++i )
4771  {
4772  SCIP_VAR** implvars;
4773  SCIP_BOUNDTYPE* impltypes;
4774  SCIP_Real* implbounds;
4775  int nimpls;
4776 
4777  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4778  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4779  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4780  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4781 
4782  for( j = 0; j < nimpls && !(*infeasible); ++j )
4783  {
4784  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4785  * implication to the aggregated variable?
4786  */
4787  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4788  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4789  NULL) );
4790  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4791  }
4792  }
4793  }
4794  SCIPimplicsFree(&var->implics, blkmem);
4795 
4796  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4797  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4798  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4799  SCIPhistoryReset(var->history);
4801 
4802  /* update flags of aggregation variable */
4803  aggvar->removable &= var->removable;
4804 
4805  /* update branching factors and priorities of both variables to be the maximum of both variables */
4806  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4807  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4808  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4809  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4810  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4811  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4812 
4813  /* update branching direction of both variables to agree to a single direction */
4814  if( scalar >= 0.0 )
4815  {
4817  {
4819  }
4820  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4821  {
4823  }
4824  else if( var->branchdirection != aggvar->branchdirection )
4825  {
4827  }
4828  }
4829  else
4830  {
4832  {
4834  }
4835  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4836  {
4838  }
4839  else if( var->branchdirection != aggvar->branchdirection )
4840  {
4842  }
4843  }
4844 
4845  if( var->probindex != -1 )
4846  {
4847  /* inform problem about the variable's status change */
4848  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4849  }
4850 
4851  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4852  * variable and the problem's objective offset
4853  */
4854  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4855 
4856  /* issue VARFIXED event */
4857  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4858 
4859  *aggregated = TRUE;
4860 
4861  return SCIP_OKAY;
4862 }
4863 
4864 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4865  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4866  *
4867  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4868  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4869  */
4870 static
4872  SCIP_SET* set, /**< global SCIP settings */
4873  BMS_BLKMEM* blkmem, /**< block memory */
4874  SCIP_STAT* stat, /**< problem statistics */
4875  SCIP_PROB* transprob, /**< tranformed problem data */
4876  SCIP_PROB* origprob, /**< original problem data */
4877  SCIP_PRIMAL* primal, /**< primal data */
4878  SCIP_TREE* tree, /**< branch and bound tree */
4879  SCIP_REOPT* reopt, /**< reoptimization data structure */
4880  SCIP_LP* lp, /**< current LP data */
4881  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4882  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4883  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4884  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4885  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4886  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4887  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4888  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4889  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4890  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4891  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4892  )
4893 {
4894  SCIP_VAR* aggvar;
4895  char aggvarname[SCIP_MAXSTRLEN];
4896  SCIP_Longint scalarxn = 0;
4897  SCIP_Longint scalarxd = 0;
4898  SCIP_Longint scalaryn = 0;
4899  SCIP_Longint scalaryd = 0;
4900  SCIP_Longint a;
4901  SCIP_Longint b;
4902  SCIP_Longint c;
4903  SCIP_Longint scm;
4904  SCIP_Longint gcd;
4905  SCIP_Longint currentclass;
4906  SCIP_Longint classstep;
4907  SCIP_Longint xsol;
4908  SCIP_Longint ysol;
4909  SCIP_Bool success;
4910  SCIP_VARTYPE vartype;
4911 
4912 #define MAXDNOM 1000000LL
4913 
4914  assert(set != NULL);
4915  assert(blkmem != NULL);
4916  assert(stat != NULL);
4917  assert(transprob != NULL);
4918  assert(origprob != NULL);
4919  assert(tree != NULL);
4920  assert(lp != NULL);
4921  assert(cliquetable != NULL);
4922  assert(branchcand != NULL);
4923  assert(eventqueue != NULL);
4924  assert(varx != NULL);
4925  assert(vary != NULL);
4926  assert(varx != vary);
4927  assert(infeasible != NULL);
4928  assert(aggregated != NULL);
4929  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4930  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4932  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4934  assert(!SCIPsetIsZero(set, scalarx));
4935  assert(!SCIPsetIsZero(set, scalary));
4936 
4937  *infeasible = FALSE;
4938  *aggregated = FALSE;
4939 
4940  /* get rational representation of coefficients */
4941  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4942  if( success )
4943  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4944  if( !success )
4945  return SCIP_OKAY;
4946  assert(scalarxd >= 1);
4947  assert(scalaryd >= 1);
4948 
4949  /* multiply equality with smallest common denominator */
4950  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4951  a = (scm/scalarxd)*scalarxn;
4952  b = (scm/scalaryd)*scalaryn;
4953  rhs *= scm;
4954 
4955  /* divide equality by the greatest common divisor of a and b */
4956  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4957  a /= gcd;
4958  b /= gcd;
4959  rhs /= gcd;
4960  assert(a != 0);
4961  assert(b != 0);
4962 
4963  /* check, if right hand side is integral */
4964  if( !SCIPsetIsFeasIntegral(set, rhs) )
4965  {
4966  *infeasible = TRUE;
4967  return SCIP_OKAY;
4968  }
4969  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4970 
4971  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
4972  return SCIP_OKAY;
4973 
4974  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4975  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4976  {
4977  /* aggregate x = - b/a*y + c/a */
4978  /*lint --e{653}*/
4979  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4980  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4981  assert(*aggregated);
4982  return SCIP_OKAY;
4983  }
4984  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4985  {
4986  /* aggregate y = - a/b*x + c/b */
4987  /*lint --e{653}*/
4988  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4989  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4990  assert(*aggregated);
4991  return SCIP_OKAY;
4992  }
4993 
4994  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4995  * common divisor. Let (x',y') be a solution of the equality
4996  * a*x + b*y == c -> a*x == c - b*y
4997  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4998  */
4999 
5000  /* find initial solution (x',y'):
5001  * - find y' such that c - b*y' is a multiple of a
5002  * - start in equivalence class c%a
5003  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5004  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5005  * - 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
5006  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5007  *
5008  * Algorithm works for a > 0 only.
5009  */
5010  if( a < 0 )
5011  {
5012  a = -a;
5013  b = -b;
5014  c = -c;
5015  }
5016  assert(0 <= a);
5017 
5018  /* search upwards from ysol = 0 */
5019  ysol = 0;
5020  currentclass = c%a;
5021  if( currentclass < 0 )
5022  currentclass += a;
5023  assert(0 <= currentclass && currentclass < a);
5024 
5025  classstep = (-b)%a;
5026 
5027  if( classstep < 0 )
5028  classstep += a;
5029  assert(0 <= classstep && classstep < a);
5030 
5031  while( currentclass != 0 )
5032  {
5033  assert(0 <= currentclass && currentclass < a);
5034  currentclass += classstep;
5035  if( currentclass >= a )
5036  currentclass -= a;
5037  ysol++;
5038  }
5039  assert(ysol < a);
5040  assert(((c - b*ysol)%a) == 0);
5041 
5042  xsol = (c - b*ysol)/a;
5043 
5044  /* determine variable type for new artificial variable:
5045  *
5046  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5047  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5048  * integral type
5049  */
5052 
5053  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5054  * - create new integer variable z with infinite bounds
5055  * - aggregate variable x = -b*z + x'
5056  * - aggregate variable y = a*z + y'
5057  * - the bounds of z are calculated automatically during aggregation
5058  */
5059  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5060  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5061  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5063  NULL, NULL, NULL, NULL, NULL) );
5064 
5065  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5066 
5067  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5068  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5069  assert(*aggregated || *infeasible);
5070 
5071  if( !(*infeasible) )
5072  {
5073  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5074  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5075  assert(*aggregated || *infeasible);
5076  }
5077 
5078  /* release z */
5079  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5080 
5081  return SCIP_OKAY;
5082 }
5083 
5084 /** performs second step of SCIPaggregateVars():
5085  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5086  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5087  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5088  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5089  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5090  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5091  *
5092  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5093  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5094  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5095  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5096  */
5098  SCIP_SET* set, /**< global SCIP settings */
5099  BMS_BLKMEM* blkmem, /**< block memory */
5100  SCIP_STAT* stat, /**< problem statistics */
5101  SCIP_PROB* transprob, /**< tranformed problem data */
5102  SCIP_PROB* origprob, /**< original problem data */
5103  SCIP_PRIMAL* primal, /**< primal data */
5104  SCIP_TREE* tree, /**< branch and bound tree */
5105  SCIP_REOPT* reopt, /**< reoptimization data structure */
5106  SCIP_LP* lp, /**< current LP data */
5107  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5108  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5109  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5110  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5111  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5112  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5113  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5114  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5115  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5116  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5117  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5118  )
5119 {
5120  SCIP_Bool easyaggr;
5121  SCIP_Real maxscalar;
5122  SCIP_Real absquot;
5123 
5124  assert(set != NULL);
5125  assert(blkmem != NULL);
5126  assert(stat != NULL);
5127  assert(transprob != NULL);
5128  assert(origprob != NULL);
5129  assert(tree != NULL);
5130  assert(lp != NULL);
5131  assert(cliquetable != NULL);
5132  assert(branchcand != NULL);
5133  assert(eventqueue != NULL);
5134  assert(varx != NULL);
5135  assert(vary != NULL);
5136  assert(varx != vary);
5137  assert(infeasible != NULL);
5138  assert(aggregated != NULL);
5139  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5140  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5141  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5142  assert(!SCIPsetIsZero(set, scalarx));
5143  assert(!SCIPsetIsZero(set, scalary));
5144 
5145  *infeasible = FALSE;
5146  *aggregated = FALSE;
5147 
5148  absquot = REALABS(scalarx / scalary);
5149  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5150  maxscalar = MAX(maxscalar, 1.0);
5151 
5152  if( absquot > maxscalar || absquot < 1 / maxscalar )
5153  return SCIP_OKAY;
5154 
5155  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5156  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5157  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5158  {
5159  SCIP_VAR* var;
5160  SCIP_Real scalar;
5161 
5162  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5163  var = vary;
5164  vary = varx;
5165  varx = var;
5166  scalar = scalary;
5167  scalary = scalarx;
5168  scalarx = scalar;
5169  }
5170 
5171  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5172  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5173  return SCIP_OKAY;
5174 
5175  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5176 
5177  /* figure out, which variable should be aggregated */
5178  easyaggr = FALSE;
5179 
5180  /* check if it is an easy aggregation that means:
5181  *
5182  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5183  */
5184  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5185  {
5187  {
5188  easyaggr = TRUE;
5189  }
5190  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5191  {
5192  easyaggr = TRUE;
5193  }
5194  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5195  {
5196  /* we have an easy aggregation if we flip the variables x and y */
5197  SCIP_VAR* var;
5198  SCIP_Real scalar;
5199 
5200  /* switch the variables, such that varx is the aggregated variable */
5201  var = vary;
5202  vary = varx;
5203  varx = var;
5204  scalar = scalary;
5205  scalary = scalarx;
5206  scalarx = scalar;
5207  easyaggr = TRUE;
5208  }
5209  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5210  {
5211  /* the aggregation is still easy if both variables are continuous */
5212  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5213  easyaggr = TRUE;
5214  }
5215  }
5216 
5217  /* did we find an "easy" aggregation? */
5218  if( easyaggr )
5219  {
5220  SCIP_Real scalar;
5221  SCIP_Real constant;
5222 
5223  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5224 
5225  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5226  scalar = -scalary/scalarx;
5227  constant = rhs/scalarx;
5228 
5229  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5230  return SCIP_OKAY;
5231 
5232  /* check aggregation for integer feasibility */
5235  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5236  {
5237  *infeasible = TRUE;
5238  return SCIP_OKAY;
5239  }
5240 
5241  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5242  * since then we would loose the corresponding divisibility property
5243  */
5244  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5245 
5246  /* aggregate the variable */
5247  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5248  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5249  assert(*aggregated || *infeasible);
5250  }
5253  {
5254  /* the variables are both integral: we have to try to find an integer aggregation */
5255  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5256  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5257  }
5258 
5259  return SCIP_OKAY;
5260 }
5261 
5262 /** converts variable into multi-aggregated variable */
5264  SCIP_VAR* var, /**< problem variable */
5265  BMS_BLKMEM* blkmem, /**< block memory */
5266  SCIP_SET* set, /**< global SCIP settings */
5267  SCIP_STAT* stat, /**< problem statistics */
5268  SCIP_PROB* transprob, /**< tranformed problem data */
5269  SCIP_PROB* origprob, /**< original problem data */
5270  SCIP_PRIMAL* primal, /**< primal data */
5271  SCIP_TREE* tree, /**< branch and bound tree */
5272  SCIP_REOPT* reopt, /**< reoptimization data structure */
5273  SCIP_LP* lp, /**< current LP data */
5274  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5275  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5276  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5277  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5278  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5279  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5280  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5281  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5282  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5283  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5284  )
5285 {
5286  SCIP_VAR** tmpvars;
5287  SCIP_Real* tmpscalars;
5288  SCIP_Real obj;
5289  SCIP_Real branchfactor;
5290  int branchpriority;
5291  SCIP_BRANCHDIR branchdirection;
5292  int nlocksdown[NLOCKTYPES];
5293  int nlocksup[NLOCKTYPES];
5294  int v;
5295  SCIP_Real tmpconstant;
5296  SCIP_Real tmpscalar;
5297  int ntmpvars;
5298  int tmpvarssize;
5299  int tmprequiredsize;
5300  int i;
5301 
5302  assert(var != NULL);
5303  assert(var->scip == set->scip);
5304  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5305  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5306  assert(naggvars == 0 || aggvars != NULL);
5307  assert(naggvars == 0 || scalars != NULL);
5308  assert(infeasible != NULL);
5309  assert(aggregated != NULL);
5310 
5311  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5312 
5313  /* check multi-aggregation on debugging solution */
5314  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5315 
5316  *infeasible = FALSE;
5317  *aggregated = FALSE;
5318 
5319  switch( SCIPvarGetStatus(var) )
5320  {
5322  if( var->data.original.transvar == NULL )
5323  {
5324  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5325  return SCIP_INVALIDDATA;
5326  }
5327  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5328  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5329  break;
5330 
5331  case SCIP_VARSTATUS_LOOSE:
5332  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5333 
5334  /* check if we would create a self-reference */
5335  ntmpvars = naggvars;
5336  tmpvarssize = naggvars;
5337  tmpconstant = constant;
5338  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5339  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5340 
5341  /* get all active variables for multi-aggregation */
5342  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5343  if( tmprequiredsize > tmpvarssize )
5344  {
5345  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5346  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5347  tmpvarssize = tmprequiredsize;
5348  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5349  assert( tmprequiredsize <= tmpvarssize );
5350  }
5351 
5352  tmpscalar = 0.0;
5353 
5354  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5355  * possible multi-aggregated variable
5356  */
5357  for( v = ntmpvars - 1; v >= 0; --v )
5358  {
5359  assert(tmpvars[v] != NULL);
5360  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5361 
5362  if( tmpvars[v]->index == var->index )
5363  {
5364  tmpscalar += tmpscalars[v];
5365  tmpvars[v] = tmpvars[ntmpvars - 1];
5366  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5367  --ntmpvars;
5368  }
5369  }
5370 
5371  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5372  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5373  {
5374  if( ntmpvars == 0 )
5375  {
5376  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5377  {
5378  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5379  goto TERMINATE;
5380  }
5381  else /* 0 = c and c != 0 */
5382  {
5383  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5384  *infeasible = TRUE;
5385  goto TERMINATE;
5386  }
5387  }
5388  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5389  {
5390  assert(tmpscalars[0] != 0.0);
5391  assert(tmpvars[0] != NULL);
5392 
5393  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5394  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5395  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5396  goto TERMINATE;
5397  }
5398  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 */
5399  {
5400  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5401 
5402  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5403  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5404 
5405  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5406  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5407  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5408 
5409  goto TERMINATE;
5410  }
5411  else
5412  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5413  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5414  */
5415  goto TERMINATE;
5416  }
5417  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5418  else if( !SCIPsetIsZero(set, tmpscalar) )
5419  {
5420  tmpscalar = 1 - tmpscalar;
5421  tmpconstant /= tmpscalar;
5422  for( v = ntmpvars - 1; v >= 0; --v )
5423  tmpscalars[v] /= tmpscalar;
5424  }
5425 
5426  /* check, if we are in one of the simple cases */
5427  if( ntmpvars == 0 )
5428  {
5429  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5430  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5431  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5432  goto TERMINATE;
5433  }
5434 
5435  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5436  if( ntmpvars == 1 )
5437  {
5438  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5439  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5440 
5441  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5442  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5443  infeasible, aggregated) );
5444 
5445  goto TERMINATE;
5446  }
5447 
5448  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5449  * empty hole list; this should be changed in the future */
5450  if( SCIPvarGetHolelistGlobal(var) != NULL )
5451  goto TERMINATE;
5452 
5453  /* if the variable is not allowed to be multi-aggregated */
5454  if( SCIPvarDoNotMultaggr(var) )
5455  {
5456  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5457  goto TERMINATE;
5458  }
5459 
5460  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5461  * variable bound variable of another variable), we have to remove it from the other variables implications or
5462  * variable bounds
5463  */
5464  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5465  assert(var->vlbs == NULL);
5466  assert(var->vubs == NULL);
5467  assert(var->implics == NULL);
5468  assert(var->cliquelist == NULL);
5469 
5470  /* set the aggregated variable's objective value to 0.0 */
5471  obj = var->obj;
5472  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5473 
5474  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5475  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5476  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5477  * objective of this variable is set to zero
5478  */
5479  SCIPlpDecNLoosevars(lp);
5480 
5481  /* unlock all rounding locks */
5482  for( i = 0; i < NLOCKTYPES; i++ )
5483  {
5484  nlocksdown[i] = var->nlocksdown[i];
5485  nlocksup[i] = var->nlocksup[i];
5486 
5487  var->nlocksdown[i] = 0;
5488  var->nlocksup[i] = 0;
5489  }
5490 
5491  /* convert variable into multi-aggregated variable */
5492  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5493  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5494  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5495  var->data.multaggr.constant = tmpconstant;
5496  var->data.multaggr.nvars = ntmpvars;
5497  var->data.multaggr.varssize = ntmpvars;
5498 
5499  /* mark variable to be non-deletable */
5501 
5502  /* relock the variable, thus increasing the locks of the aggregation variables */
5503  for( i = 0; i < NLOCKTYPES; i++ )
5504  {
5505  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5506  }
5507 
5508  /* update flags and branching factors and priorities of aggregation variables;
5509  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5510  */
5511  branchfactor = var->branchfactor;
5512  branchpriority = var->branchpriority;
5513  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5514 
5515  for( v = 0; v < ntmpvars; ++v )
5516  {
5517  assert(tmpvars[v] != NULL);
5518  tmpvars[v]->removable &= var->removable;
5519  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5520  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5521 
5522  /* mark variable to be non-deletable */
5523  SCIPvarMarkNotDeletable(tmpvars[v]);
5524  }
5525  for( v = 0; v < ntmpvars; ++v )
5526  {
5527  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5528  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5529  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5530  {
5531  if( tmpscalars[v] >= 0.0 )
5532  {
5533  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5534  }
5535  else
5536  {
5537  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5538  }
5539  }
5540  }
5541  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5542  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5543 
5544  if( var->probindex != -1 )
5545  {
5546  /* inform problem about the variable's status change */
5547  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5548  }
5549 
5550  /* issue VARFIXED event */
5551  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5552 
5553  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5554  * variables and the problem's objective offset
5555  */
5556  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5557 
5558  *aggregated = TRUE;
5559 
5560  TERMINATE:
5561  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5562  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5563 
5564  break;
5565 
5566  case SCIP_VARSTATUS_COLUMN:
5567  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5568  return SCIP_INVALIDDATA;
5569 
5570  case SCIP_VARSTATUS_FIXED:
5571  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5572  return SCIP_INVALIDDATA;
5573 
5575  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5576  return SCIP_INVALIDDATA;
5577 
5579  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5580  return SCIP_INVALIDDATA;
5581 
5583  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5584  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5585  */
5586  assert(SCIPsetIsZero(set, var->obj));
5587  assert(var->negatedvar != NULL);
5589  assert(var->negatedvar->negatedvar == var);
5590 
5591  /* switch the signs of the aggregation scalars */
5592  for( v = 0; v < naggvars; ++v )
5593  scalars[v] *= -1.0;
5594 
5595  /* perform the multi aggregation on the negation variable */
5596  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5597  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5598  var->data.negate.constant - constant, infeasible, aggregated) );
5599 
5600  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5601  for( v = 0; v < naggvars; ++v )
5602  scalars[v] *= -1.0;
5603  break;
5604 
5605  default:
5606  SCIPerrorMessage("unknown variable status\n");
5607  return SCIP_INVALIDDATA;
5608  }
5609 
5610  return SCIP_OKAY;
5611 }
5612 
5613 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5614  * or for original variables the same variable is returned
5615  */
5616 static
5618  SCIP_VAR* var /**< problem variable */
5619  )
5620 {
5621  SCIP_VAR* retvar;
5622 
5623  assert(var != NULL);
5624 
5625  retvar = var;
5626 
5627  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5628 
5629  while( TRUE ) /*lint !e716 */
5630  {
5631  assert(retvar != NULL);
5632 
5633  switch( SCIPvarGetStatus(retvar) )
5634  {
5636  case SCIP_VARSTATUS_LOOSE:
5637  case SCIP_VARSTATUS_COLUMN:
5638  case SCIP_VARSTATUS_FIXED:
5639  return retvar;
5640 
5642  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5643  if ( retvar->data.multaggr.nvars == 1 )
5644  retvar = retvar->data.multaggr.vars[0];
5645  else
5646  return retvar;
5647  break;
5648 
5650  retvar = retvar->data.aggregate.var;
5651  break;
5652 
5654  retvar = retvar->negatedvar;
5655  break;
5656 
5657  default:
5658  SCIPerrorMessage("unknown variable status\n");
5659  SCIPABORT();
5660  return NULL; /*lint !e527*/
5661  }
5662  }
5663 }
5664 
5665 /** returns whether variable is not allowed to be multi-aggregated */
5667  SCIP_VAR* var /**< problem variable */
5668  )
5669 {
5670  SCIP_VAR* retvar;
5671 
5672  assert(var != NULL);
5673 
5674  retvar = varGetActiveVar(var);
5675  assert(retvar != NULL);
5676 
5677  switch( SCIPvarGetStatus(retvar) )
5678  {
5680  case SCIP_VARSTATUS_LOOSE:
5681  case SCIP_VARSTATUS_COLUMN:
5682  case SCIP_VARSTATUS_FIXED:
5683  return retvar->donotmultaggr;
5684 
5686  return FALSE;
5687 
5690  default:
5691  SCIPerrorMessage("wrong variable status\n");
5692  SCIPABORT();
5693  return FALSE; /*lint !e527 */
5694  }
5695 }
5696 
5697 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5698  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5699  * negated variable is created
5700  */
5702  SCIP_VAR* var, /**< problem variable to negate */
5703  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5704  SCIP_SET* set, /**< global SCIP settings */
5705  SCIP_STAT* stat, /**< problem statistics */
5706  SCIP_VAR** negvar /**< pointer to store the negated variable */
5707  )
5708 {
5709  assert(var != NULL);
5710  assert(var->scip == set->scip);
5711  assert(negvar != NULL);
5712 
5713  /* check, if we already created the negated variable */
5714  if( var->negatedvar == NULL )
5715  {
5716  char negvarname[SCIP_MAXSTRLEN];
5717 
5718  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5719 
5720  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5721 
5722  /* negation is only possible for bounded variables */
5723  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5724  {
5725  SCIPerrorMessage("cannot negate unbounded variable\n");
5726  return SCIP_INVALIDDATA;
5727  }
5728 
5729  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5730 
5731  /* create negated variable */
5732  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5733  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5734  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5735  if( SCIPvarIsBinary(var) )
5736  (*negvar)->data.negate.constant = 1.0;
5737  else
5738  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5739 
5740  /* create event filter for transformed variable */
5741  if( SCIPvarIsTransformed(var) )
5742  {
5743  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5744  }
5745 
5746  /* set the bounds corresponding to the negation variable */
5747  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5748  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5749  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5750  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5751  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5752 
5753  /* link the variables together */
5754  var->negatedvar = *negvar;
5755  (*negvar)->negatedvar = var;
5756 
5757  /* mark both variables to be non-deletable */
5759  SCIPvarMarkNotDeletable(*negvar);
5760 
5761  /* copy the branch factor and priority, and use the negative preferred branching direction */
5762  (*negvar)->branchfactor = var->branchfactor;
5763  (*negvar)->branchpriority = var->branchpriority;
5764  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5765 
5766  /* copy doNotMultiaggr status */
5767  (*negvar)->donotmultaggr = var->donotmultaggr;
5768 
5769  /* copy lazy bounds (they have to be flipped) */
5770  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5771  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5772 
5773  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5774  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5775  assert((*negvar)->nuses == 1);
5776  }
5777  assert(var->negatedvar != NULL);
5778 
5779  /* return the negated variable */
5780  *negvar = var->negatedvar;
5781 
5782  /* exactly one variable of the negation pair has to be marked as negated variable */
5784 
5785  return SCIP_OKAY;
5786 }
5787 
5788 /** informs variable that its position in problem's vars array changed */
5789 static
5790 void varSetProbindex(
5791  SCIP_VAR* var, /**< problem variable */
5792  int probindex /**< new problem index of variable (-1 for removal) */
5793  )
5794 {
5795  assert(var != NULL);
5796  assert(probindex >= 0 || var->vlbs == NULL);
5797  assert(probindex >= 0 || var->vubs == NULL);
5798  assert(probindex >= 0 || var->implics == NULL);
5799 
5800  var->probindex = probindex;
5802  {
5803  assert(var->data.col != NULL);
5804  var->data.col->var_probindex = probindex;
5805  }
5806 }
5807 
5808 /** informs variable that its position in problem's vars array changed */
5809 void SCIPvarSetProbindex(
5810  SCIP_VAR* var, /**< problem variable */
5811  int probindex /**< new problem index of variable */
5812  )
5813 {
5814  assert(var != NULL);
5815  assert(probindex >= 0);
5816 
5817  varSetProbindex(var, probindex);
5818 }
5819 
5820 /** gives the variable a new name
5821  *
5822  * @note the old pointer is overwritten, which might result in a memory leakage
5823  */
5825  SCIP_VAR* var, /**< problem variable */
5826  const char* name /**< new name of variable */
5827  )
5828 {
5829  assert(var != NULL);
5830  assert(name != NULL);
5831 
5832  var->name = (char*)name;
5833 }
5834 
5835 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5836  * implication graph;
5837  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5838  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5839  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5840  * than removing the variables one by one, each time updating all lists of the other variables.
5841  */
5843  SCIP_VAR* var, /**< problem variable */
5844  BMS_BLKMEM* blkmem, /**< block memory buffer */
5845  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5846  SCIP_SET* set, /**< global SCIP settings */
5847  SCIP_Bool final /**< is this the final removal of all problem variables? */
5848  )
5849 {
5850  assert(SCIPvarGetProbindex(var) >= 0);
5851  assert(var->scip == set->scip);
5852 
5853  /* if the variable is active in the transformed problem, remove it from the implication graph */
5854  if( SCIPvarIsTransformed(var)
5856  {
5857  if( final )
5858  {
5859  /* just destroy the data structures */
5860  SCIPvboundsFree(&var->vlbs, blkmem);
5861  SCIPvboundsFree(&var->vubs, blkmem);
5862  SCIPimplicsFree(&var->implics, blkmem);
5863  }
5864  else
5865  {
5866  /* unlink the variable from all other variables' lists and free the data structures */
5867  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5868  }
5869  }
5870 
5871  /* mark the variable to be no longer a member of the problem */
5872  varSetProbindex(var, -1);
5873 
5874  return SCIP_OKAY;
5875 }
5876 
5877 /** marks the variable to be deleted from the problem */
5878 void SCIPvarMarkDeleted(
5879  SCIP_VAR* var /**< problem variable */
5880  )
5881 {
5882  assert(var != NULL);
5883  assert(var->probindex != -1);
5884 
5885  var->deleted = TRUE;
5886 }
5887 
5888 /** marks the variable to not to be multi-aggregated */
5890  SCIP_VAR* var /**< problem variable */
5891  )
5892 {
5893  SCIP_VAR* retvar;
5894 
5895  assert(var != NULL);
5896 
5897  retvar = varGetActiveVar(var);
5898  assert(retvar != NULL);
5899 
5900  switch( SCIPvarGetStatus(retvar) )
5901  {
5903  case SCIP_VARSTATUS_LOOSE:
5904  case SCIP_VARSTATUS_COLUMN:
5905  case SCIP_VARSTATUS_FIXED:
5906  retvar->donotmultaggr = TRUE;
5907  break;
5908 
5910  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5911  return SCIP_INVALIDDATA;
5912 
5915  default:
5916  SCIPerrorMessage("wrong variable status\n");
5917  return SCIP_INVALIDDATA;
5918  }
5919 
5920  return SCIP_OKAY;
5921 }
5922 
5923 /** changes type of variable; cannot be called, if var belongs to a problem */
5925  SCIP_VAR* var, /**< problem variable to change */
5926  SCIP_VARTYPE vartype /**< new type of variable */
5927  )
5928 {
5929  assert(var != NULL);
5930 
5931  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5932 
5933  if( var->probindex >= 0 )
5934  {
5935  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5936  return SCIP_INVALIDDATA;
5937  }
5938 
5939  var->vartype = vartype; /*lint !e641*/
5940  if( var->negatedvar != NULL )
5941  var->negatedvar->vartype = vartype; /*lint !e641*/
5942 
5943  return SCIP_OKAY;
5944 }
5945 
5946 /** appends OBJCHANGED event to the event queue */
5947 static
5949  SCIP_VAR* var, /**< problem variable to change */
5950  BMS_BLKMEM* blkmem, /**< block memory */
5951  SCIP_SET* set, /**< global SCIP settings */
5952  SCIP_PRIMAL* primal, /**< primal data */
5953  SCIP_LP* lp, /**< current LP data */
5954  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5955  SCIP_Real oldobj, /**< old objective value for variable */
5956  SCIP_Real newobj /**< new objective value for variable */
5957  )
5958 {
5959  SCIP_EVENT* event;
5960 
5961  assert(var != NULL);
5962  assert(var->scip == set->scip);
5963  assert(var->eventfilter != NULL);
5965  assert(SCIPvarIsTransformed(var));
5966  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5967 
5968  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5969  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5970 
5971  return SCIP_OKAY;
5972 }
5973 
5974 /** changes objective value of variable */
5976  SCIP_VAR* var, /**< variable to change */
5977  BMS_BLKMEM* blkmem, /**< block memory */
5978  SCIP_SET* set, /**< global SCIP settings */
5979  SCIP_PROB* prob, /**< problem data */
5980  SCIP_PRIMAL* primal, /**< primal data */
5981  SCIP_LP* lp, /**< current LP data */
5982  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5983  SCIP_Real newobj /**< new objective value for variable */
5984  )
5985 {
5986  SCIP_Real oldobj;
5987 
5988  assert(var != NULL);
5989  assert(set != NULL);
5990  assert(var->scip == set->scip);
5991 
5992  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5993 
5994  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5995  {
5996  switch( SCIPvarGetStatus(var) )
5997  {
5999  if( var->data.original.transvar != NULL )
6000  {
6001  assert(SCIPprobIsTransformed(prob));
6002 
6003  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6004  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6005  }
6006  else
6007  assert(set->stage == SCIP_STAGE_PROBLEM);
6008 
6009  var->obj = newobj;
6010  var->unchangedobj = newobj;
6011 
6012  break;
6013 
6014  case SCIP_VARSTATUS_LOOSE:
6015  case SCIP_VARSTATUS_COLUMN:
6016  oldobj = var->obj;
6017  var->obj = newobj;
6018 
6019  /* update unchanged objective value of variable */
6020  if( !lp->divingobjchg )
6021  var->unchangedobj = newobj;
6022 
6023  /* update the number of variables with non-zero objective coefficient;
6024  * we only want to do the update, if the variable is added to the problem;
6025  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6026  */
6027  if( SCIPvarIsActive(var) )
6028  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6029 
6030  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6031  break;
6032 
6033  case SCIP_VARSTATUS_FIXED:
6037  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6038  return SCIP_INVALIDDATA;
6039 
6040  default:
6041  SCIPerrorMessage("unknown variable status\n");
6042  return SCIP_INVALIDDATA;
6043  }
6044  }
6045 
6046  return SCIP_OKAY;
6047 }
6048 
6049 /** adds value to objective value of variable */
6051  SCIP_VAR* var, /**< variable to change */
6052  BMS_BLKMEM* blkmem, /**< block memory */
6053  SCIP_SET* set, /**< global SCIP settings */
6054  SCIP_STAT* stat, /**< problem statistics */
6055  SCIP_PROB* transprob, /**< transformed problem data */
6056  SCIP_PROB* origprob, /**< original problem data */
6057  SCIP_PRIMAL* primal, /**< primal data */
6058  SCIP_TREE* tree, /**< branch and bound tree */
6059  SCIP_REOPT* reopt, /**< reoptimization data structure */
6060  SCIP_LP* lp, /**< current LP data */
6061  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6062  SCIP_Real addobj /**< additional objective value for variable */
6063  )
6064 {
6065  assert(var != NULL);
6066  assert(set != NULL);
6067  assert(var->scip == set->scip);
6068  assert(set->stage < SCIP_STAGE_INITSOLVE);
6069 
6070  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6071 
6072  if( !SCIPsetIsZero(set, addobj) )
6073  {
6074  SCIP_Real oldobj;
6075  int i;
6076 
6077  switch( SCIPvarGetStatus(var) )
6078  {
6080  if( var->data.original.transvar != NULL )
6081  {
6082  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6083  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6084  }
6085  else
6086  assert(set->stage == SCIP_STAGE_PROBLEM);
6087 
6088  var->obj += addobj;
6089  var->unchangedobj += addobj;
6090  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6091 
6092  break;
6093 
6094  case SCIP_VARSTATUS_LOOSE:
6095  case SCIP_VARSTATUS_COLUMN:
6096  oldobj = var->obj;
6097  var->obj += addobj;
6098 
6099  /* update unchanged objective value of variable */
6100  if( !lp->divingobjchg )
6101  {
6102  var->unchangedobj += addobj;
6103  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6104  }
6105 
6106  /* update the number of variables with non-zero objective coefficient;
6107  * we only want to do the update, if the variable is added to the problem;
6108  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6109  */
6110  if( SCIPvarIsActive(var) )
6111  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6112 
6113  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6114  break;
6115 
6116  case SCIP_VARSTATUS_FIXED:
6117  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6118  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6119  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6120  break;
6121 
6123  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6124  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6125  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6126  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6127  lp, eventqueue, var->data.aggregate.scalar * addobj) );
6128  break;
6129 
6131  assert(!var->donotmultaggr);
6132  /* 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 */
6133  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6134  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6135  for( i = 0; i < var->data.multaggr.nvars; ++i )
6136  {
6137  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6138  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6139  }
6140  break;
6141 
6143  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6144  assert(var->negatedvar != NULL);
6146  assert(var->negatedvar->negatedvar == var);
6147  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6148  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6149  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6150  eventqueue, -addobj) );
6151  break;
6152 
6153  default:
6154  SCIPerrorMessage("unknown variable status\n");
6155  return SCIP_INVALIDDATA;
6156  }
6157  }
6158 
6159  return SCIP_OKAY;
6160 }
6161 
6162 /** changes objective value of variable in current dive */
6164  SCIP_VAR* var, /**< problem variable to change */
6165  SCIP_SET* set, /**< global SCIP settings */
6166  SCIP_LP* lp, /**< current LP data */
6167  SCIP_Real newobj /**< new objective value for variable */
6168  )
6169 {
6170  assert(var != NULL);
6171  assert(set != NULL);
6172  assert(var->scip == set->scip);
6173  assert(lp != NULL);
6174 
6175  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6176 
6177  if( SCIPsetIsZero(set, newobj) )
6178  newobj = 0.0;
6179 
6180  /* change objective value of attached variables */
6181  switch( SCIPvarGetStatus(var) )
6182  {
6184  assert(var->data.original.transvar != NULL);
6185  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6186  break;
6187 
6188  case SCIP_VARSTATUS_COLUMN:
6189  assert(var->data.col != NULL);
6190  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6191  break;
6192 
6193  case SCIP_VARSTATUS_LOOSE:
6194  case SCIP_VARSTATUS_FIXED:
6195  /* nothing to do here: only the constant shift in objective function would change */
6196  break;
6197 
6198  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6199  assert(var->data.aggregate.var != NULL);
6200  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6201  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6202  /* the constant can be ignored, because it would only affect the objective shift */
6203  break;
6204 
6206  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6207  return SCIP_INVALIDDATA;
6208 
6209  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6210  assert(var->negatedvar != NULL);
6212  assert(var->negatedvar->negatedvar == var);
6213  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6214  /* the offset can be ignored, because it would only affect the objective shift */
6215  break;
6216 
6217  default:
6218  SCIPerrorMessage("unknown variable status\n");
6219  return SCIP_INVALIDDATA;
6220  }
6221 
6222  return SCIP_OKAY;
6223 }
6224 
6225 /** adjust lower bound to integral value, if variable is integral */
6226 void SCIPvarAdjustLb(
6227  SCIP_VAR* var, /**< problem variable */
6228  SCIP_SET* set, /**< global SCIP settings */
6229  SCIP_Real* lb /**< pointer to lower bound to adjust */
6230  )
6231 {
6232  assert(var != NULL);
6233  assert(set != NULL);
6234  assert(var->scip == set->scip);
6235  assert(lb != NULL);
6236 
6237  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6238 
6239  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6240 }
6241 
6242 /** adjust upper bound to integral value, if variable is integral */
6243 void SCIPvarAdjustUb(
6244  SCIP_VAR* var, /**< problem variable */
6245  SCIP_SET* set, /**< global SCIP settings */
6246  SCIP_Real* ub /**< pointer to upper bound to adjust */
6247  )
6248 {
6249  assert(var != NULL);
6250  assert(set != NULL);
6251  assert(var->scip == set->scip);
6252  assert(ub != NULL);
6253 
6254  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6255 
6256  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6257 }
6258 
6259 /** adjust lower or upper bound to integral value, if variable is integral */
6260 void SCIPvarAdjustBd(
6261  SCIP_VAR* var, /**< problem variable */
6262  SCIP_SET* set, /**< global SCIP settings */
6263  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6264  SCIP_Real* bd /**< pointer to bound to adjust */
6265  )
6266 {
6267  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6268 
6269  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6270  SCIPvarAdjustLb(var, set, bd);
6271  else
6272  SCIPvarAdjustUb(var, set, bd);
6273 }
6274 
6275 /** changes lower bound of original variable in original problem */
6277  SCIP_VAR* var, /**< problem variable to change */
6278  SCIP_SET* set, /**< global SCIP settings */
6279  SCIP_Real newbound /**< new bound for variable */
6280  )
6281 {
6282  int i;
6283 
6284  assert(var != NULL);
6285  assert(!SCIPvarIsTransformed(var));
6287  assert(set != NULL);
6288  assert(var->scip == set->scip);
6289  assert(set->stage == SCIP_STAGE_PROBLEM);
6290 
6291  /* check that the bound is feasible */
6292  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6293  /* adjust bound to integral value if variable is of integral type */
6294  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6295 
6296  if( SCIPsetIsZero(set, newbound) )
6297  newbound = 0.0;
6298 
6299  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6301  {
6302  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6303  var->name, var->data.original.origdom.lb, newbound);
6304 
6305  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6306  return SCIP_OKAY;
6307 
6308  /* change the bound */
6309  var->data.original.origdom.lb = newbound;
6310  }
6311  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6312  {
6313  assert( var->negatedvar != NULL );
6314  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6315  }
6316 
6317  /* process parent variables */
6318  for( i = 0; i < var->nparentvars; ++i )
6319  {
6320  SCIP_VAR* parentvar;
6321 
6322  parentvar = var->parentvars[i];
6323  assert(parentvar != NULL);
6324  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6325  assert(parentvar->negatedvar == var);
6326  assert(var->negatedvar == parentvar);
6327 
6328  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6329  }
6330 
6331  return SCIP_OKAY;
6332 }
6333 
6334 /** changes upper bound of original variable in original problem */
6336  SCIP_VAR* var, /**< problem variable to change */
6337  SCIP_SET* set, /**< global SCIP settings */
6338  SCIP_Real newbound /**< new bound for variable */
6339  )
6340 {
6341  int i;
6342 
6343  assert(var != NULL);
6344  assert(!SCIPvarIsTransformed(var));
6346  assert(set != NULL);
6347  assert(var->scip == set->scip);
6348  assert(set->stage == SCIP_STAGE_PROBLEM);
6349 
6350  /* check that the bound is feasible */
6351  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6352  /* adjust bound to integral value if variable is of integral type */
6353  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6354 
6355  if( SCIPsetIsZero(set, newbound) )
6356  newbound = 0.0;
6357 
6358  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6360  {
6361  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6362  var->name, var->data.original.origdom.ub, newbound);
6363 
6364  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6365  return SCIP_OKAY;
6366 
6367  /* change the bound */
6368  var->data.original.origdom.ub = newbound;
6369  }
6370  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6371  {
6372  assert( var->negatedvar != NULL );
6373  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6374  }
6375 
6376  /* process parent variables */
6377  for( i = 0; i < var->nparentvars; ++i )
6378  {
6379  SCIP_VAR* parentvar;
6380 
6381  parentvar = var->parentvars[i];
6382  assert(parentvar != NULL);
6383  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6384  assert(parentvar->negatedvar == var);
6385  assert(var->negatedvar == parentvar);
6386 
6387  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6388  }
6389 
6390  return SCIP_OKAY;
6391 }
6392 
6393 /** appends GLBCHANGED event to the event queue */
6394 static
6396  SCIP_VAR* var, /**< problem variable to change */
6397  BMS_BLKMEM* blkmem, /**< block memory */
6398  SCIP_SET* set, /**< global SCIP settings */
6399  SCIP_LP* lp, /**< current LP data */
6400  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6401  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6402  SCIP_Real oldbound, /**< old lower bound for variable */
6403  SCIP_Real newbound /**< new lower bound for variable */
6404  )
6405 {
6406  assert(var != NULL);
6407  assert(var->eventfilter != NULL);
6408  assert(SCIPvarIsTransformed(var));
6409  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6410  assert(set != NULL);
6411  assert(var->scip == set->scip);
6412 
6413  /* check, if the variable is being tracked for bound changes
6414  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6415  */
6416  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6419  {
6420  SCIP_EVENT* event;
6421 
6422  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6423 
6424  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6425  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6426  }
6427 
6428  return SCIP_OKAY;
6429 }
6430 
6431 /** appends GUBCHANGED event to the event queue */
6432 static
6434  SCIP_VAR* var, /**< problem variable to change */
6435  BMS_BLKMEM* blkmem, /**< block memory */
6436  SCIP_SET* set, /**< global SCIP settings */
6437  SCIP_LP* lp, /**< current LP data */
6438  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6439  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6440  SCIP_Real oldbound, /**< old lower bound for variable */
6441  SCIP_Real newbound /**< new lower bound for variable */
6442  )
6443 {
6444  assert(var != NULL);
6445  assert(var->eventfilter != NULL);
6446  assert(SCIPvarIsTransformed(var));
6447  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6448  assert(set != NULL);
6449  assert(var->scip == set->scip);
6450 
6451  /* check, if the variable is being tracked for bound changes
6452  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6453  */
6454  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6457  {
6458  SCIP_EVENT* event;
6459 
6460  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6461 
6462  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6463  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6464  }
6465 
6466  return SCIP_OKAY;
6467 }
6468 
6469 /** appends GHOLEADDED event to the event queue */
6470 static
6472  SCIP_VAR* var, /**< problem variable to change */
6473  BMS_BLKMEM* blkmem, /**< block memory */
6474  SCIP_SET* set, /**< global SCIP settings */
6475  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6476  SCIP_Real left, /**< left bound of open interval in new hole */
6477  SCIP_Real right /**< right bound of open interval in new hole */
6478  )
6479 {
6480  assert(var != NULL);
6481  assert(var->eventfilter != NULL);
6482  assert(SCIPvarIsTransformed(var));
6483  assert(set != NULL);
6484  assert(var->scip == set->scip);
6485  assert(SCIPsetIsLT(set, left, right));
6486 
6487  /* check, if the variable is being tracked for bound changes */
6488  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6489  {
6490  SCIP_EVENT* event;
6491 
6492  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6493 
6494  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6495  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6496  }
6497 
6498  return SCIP_OKAY;
6499 }
6500 
6501 /** increases root bound change statistics after a global bound change */
6502 static
6503 void varIncRootboundchgs(
6504  SCIP_VAR* var, /**< problem variable to change */
6505  SCIP_SET* set, /**< global SCIP settings */
6506  SCIP_STAT* stat /**< problem statistics */
6507  )
6508 {
6509  assert(var != NULL);
6510  assert(set != NULL);
6511  assert(var->scip == set->scip);
6512  assert(stat != NULL);
6513 
6514  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6515  {
6516  stat->nrootboundchgs++;
6517  stat->nrootboundchgsrun++;
6518  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6519  {
6520  stat->nrootintfixings++;
6521  stat->nrootintfixingsrun++;
6522  }
6523  }
6524 }
6525 
6526 /* forward declaration, because both methods call each other recursively */
6527 
6528 /* performs the current change in upper bound, changes all parents accordingly */
6529 static
6531  SCIP_VAR* var, /**< problem variable to change */
6532  BMS_BLKMEM* blkmem, /**< block memory */
6533  SCIP_SET* set, /**< global SCIP settings */
6534  SCIP_STAT* stat, /**< problem statistics */
6535  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6536  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6537  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6538  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6539  SCIP_Real newbound /**< new bound for variable */
6540  );
6541 
6542 /** performs the current change in lower bound, changes all parents accordingly */
6543 static
6545  SCIP_VAR* var, /**< problem variable to change */
6546  BMS_BLKMEM* blkmem, /**< block memory */
6547  SCIP_SET* set, /**< global SCIP settings */
6548  SCIP_STAT* stat, /**< problem statistics */
6549  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6550  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6551  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6552  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6553  SCIP_Real newbound /**< new bound for variable */
6554  )
6555 {
6556  SCIP_VAR* parentvar;
6557  SCIP_Real oldbound;
6558  int i;
6559 
6560  assert(var != NULL);
6561  /* local domains can violate global bounds but not more than feasibility epsilon */
6562  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6563  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6564  assert(blkmem != NULL);
6565  assert(set != NULL);
6566  assert(var->scip == set->scip);
6567  assert(stat != NULL);
6568 
6569  /* adjust bound to integral value if variable is of integral type */
6570  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6571 
6572  /* check that the bound is feasible */
6573  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6574  {
6575  /* due to numerics we only want to be feasible in feasibility tolerance */
6576  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6577  newbound = var->glbdom.ub;
6578  }
6579  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6580 
6581  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6582 
6583  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6584 
6585  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6586  return SCIP_OKAY;
6587 
6588  /* check bound on debugging solution */
6589  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6590 
6591  /* change the bound */
6592  oldbound = var->glbdom.lb;
6593  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6594  var->glbdom.lb = newbound;
6595  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6596  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6597 
6598  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6599  {
6600  /* merges overlapping holes into single holes, moves bounds respectively */
6601  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6602  }
6603 
6604  /* update the root bound changes counters */
6605  varIncRootboundchgs(var, set, stat);
6606 
6607  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6608  * redundant bound changes to be branching decisions
6609  */
6610  for( i = 0; i < var->nlbchginfos; ++i )
6611  {
6612  assert(var->lbchginfos[i].var == var);
6613 
6614  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6615  {
6616  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6617  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6618  var->lbchginfos[i].oldbound = var->glbdom.lb;
6619  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6620  {
6621  /* this bound change is redundant due to the new global bound */
6622  var->lbchginfos[i].newbound = var->glbdom.lb;
6623  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6624  var->lbchginfos[i].redundant = TRUE;
6625  }
6626  else
6627  break; /* from now on, the remaining local bound changes are not redundant */
6628  }
6629  else
6630  break; /* from now on, the remaining local bound changes are not redundant */
6631  }
6632 
6633  /* remove redundant implications and variable bounds */
6635  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6636  {
6637  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6638  }
6639 
6640  /* issue bound change event */
6641  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6642  if( var->eventfilter != NULL )
6643  {
6644  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6645  }
6646 
6647  /* process parent variables */
6648  for( i = 0; i < var->nparentvars; ++i )
6649  {
6650  parentvar = var->parentvars[i];
6651  assert(parentvar != NULL);
6652 
6653  switch( SCIPvarGetStatus(parentvar) )
6654  {
6656  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6657  break;
6658 
6659  case SCIP_VARSTATUS_COLUMN:
6660  case SCIP_VARSTATUS_LOOSE:
6661  case SCIP_VARSTATUS_FIXED:
6663  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6664  return SCIP_INVALIDDATA;
6665 
6666  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6667  assert(parentvar->data.aggregate.var == var);
6668  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6669  {
6670  SCIP_Real parentnewbound;
6671 
6672  /* a > 0 -> change lower bound of y */
6673  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6674  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6675  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6676 
6677  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6678  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6679  else
6680  parentnewbound = newbound;
6681  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6682  }
6683  else
6684  {
6685  SCIP_Real parentnewbound;
6686 
6687  /* a < 0 -> change upper bound of y */
6688  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6689  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6690  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6691  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6692 
6693  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6694  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6695  else
6696  parentnewbound = -newbound;
6697  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6698  }
6699  break;
6700 
6701  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6702  assert(parentvar->negatedvar != NULL);
6703  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6704  assert(parentvar->negatedvar->negatedvar == parentvar);
6705  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6706  parentvar->data.negate.constant - newbound) );
6707  break;
6708 
6709  default:
6710  SCIPerrorMessage("unknown variable status\n");
6711  return SCIP_INVALIDDATA;
6712  }
6713  }
6714 
6715  return SCIP_OKAY;
6716 }
6717 
6718 /** performs the current change in upper bound, changes all parents accordingly */
6719 static
6721  SCIP_VAR* var, /**< problem variable to change */
6722  BMS_BLKMEM* blkmem, /**< block memory */
6723  SCIP_SET* set, /**< global SCIP settings */
6724  SCIP_STAT* stat, /**< problem statistics */
6725  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6726  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6727  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6728  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6729  SCIP_Real newbound /**< new bound for variable */
6730  )
6731 {
6732  SCIP_VAR* parentvar;
6733  SCIP_Real oldbound;
6734  int i;
6735 
6736  assert(var != NULL);
6737  /* local domains can violate global bounds but not more than feasibility epsilon */
6738  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6739  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6740  assert(blkmem != NULL);
6741  assert(set != NULL);
6742  assert(var->scip == set->scip);
6743  assert(stat != NULL);
6744 
6745  /* adjust bound to integral value if variable is of integral type */
6746  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6747 
6748  /* check that the bound is feasible */
6749  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6750  {
6751  /* due to numerics we only want to be feasible in feasibility tolerance */
6752  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6753  newbound = var->glbdom.lb;
6754  }
6755  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6756 
6757  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6758 
6759  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6760 
6761  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6762  return SCIP_OKAY;
6763 
6764  /* check bound on debugging solution */
6765  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6766 
6767  /* change the bound */
6768  oldbound = var->glbdom.ub;
6769  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6770  var->glbdom.ub = newbound;
6771  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6772  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6773 
6774  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6775  {
6776  /* merges overlapping holes into single holes, moves bounds respectively */
6777  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6778  }
6779 
6780  /* update the root bound changes counters */
6781  varIncRootboundchgs(var, set, stat);
6782 
6783  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6784  * redundant bound changes to be branching decisions
6785  */
6786  for( i = 0; i < var->nubchginfos; ++i )
6787  {
6788  assert(var->ubchginfos[i].var == var);
6789  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6790  {
6791  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6792  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6793  var->ubchginfos[i].oldbound = var->glbdom.ub;
6794  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6795  {
6796  /* this bound change is redundant due to the new global bound */
6797  var->ubchginfos[i].newbound = var->glbdom.ub;
6798  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6799  var->ubchginfos[i].redundant = TRUE;
6800  }
6801  else
6802  break; /* from now on, the remaining local bound changes are not redundant */
6803  }
6804  else
6805  break; /* from now on, the remaining local bound changes are not redundant */
6806  }
6807 
6808  /* remove redundant implications and variable bounds */
6810  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6811  {
6812  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6813  }
6814 
6815  /* issue bound change event */
6816  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6817  if( var->eventfilter != NULL )
6818  {
6819  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6820  }
6821 
6822  /* process parent variables */
6823  for( i = 0; i < var->nparentvars; ++i )
6824  {
6825  parentvar = var->parentvars[i];
6826  assert(parentvar != NULL);
6827 
6828  switch( SCIPvarGetStatus(parentvar) )
6829  {
6831  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6832  break;
6833 
6834  case SCIP_VARSTATUS_COLUMN:
6835  case SCIP_VARSTATUS_LOOSE:
6836  case SCIP_VARSTATUS_FIXED:
6838  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6839  return SCIP_INVALIDDATA;
6840 
6841  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6842  assert(parentvar->data.aggregate.var == var);
6843  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6844  {
6845  SCIP_Real parentnewbound;
6846 
6847  /* a > 0 -> change upper bound of y */
6848  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
6849  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6850  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6851  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6852  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6853  else
6854  parentnewbound = newbound;
6855  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6856  }
6857  else
6858  {
6859  SCIP_Real parentnewbound;
6860 
6861  /* a < 0 -> change lower bound of y */
6862  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6863  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
6864  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6865  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6866  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6867  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6868  else
6869  parentnewbound = -newbound;
6870  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6871  }
6872  break;
6873 
6874  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6875  assert(parentvar->negatedvar != NULL);
6876  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6877  assert(parentvar->negatedvar->negatedvar == parentvar);
6878  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6879  parentvar->data.negate.constant - newbound) );
6880  break;
6881 
6882  default:
6883  SCIPerrorMessage("unknown variable status\n");
6884  return SCIP_INVALIDDATA;
6885  }
6886  }
6887 
6888  return SCIP_OKAY;
6889 }
6890 
6891 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6892  * updates local lower bound if the global bound is tighter
6893  */
6895  SCIP_VAR* var, /**< problem variable to change */
6896  BMS_BLKMEM* blkmem, /**< block memory */
6897  SCIP_SET* set, /**< global SCIP settings */
6898  SCIP_STAT* stat, /**< problem statistics */
6899  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6900  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6901  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6902  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6903  SCIP_Real newbound /**< new bound for variable */
6904  )
6905 {
6906  assert(var != NULL);
6907  assert(blkmem != NULL);
6908  assert(set != NULL);
6909  assert(var->scip == set->scip);
6910 
6911  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6912  * of the domain within feastol
6913  */
6914  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6915 
6916  /* adjust bound to integral value if variable is of integral type */
6917  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6918 
6919  /* check that the adjusted bound is feasible
6920  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6921  * here because we reset bounds to their original value!
6922  */
6923  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6924 
6925  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6926  {
6927  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6928  newbound = MIN(newbound, var->glbdom.ub);
6929  }
6930  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6931 
6932  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6933  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6934  */
6935  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6936 
6937  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6938 
6939  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6940  return SCIP_OKAY;
6941 
6942  /* change bounds of attached variables */
6943  switch( SCIPvarGetStatus(var) )
6944  {
6946  if( var->data.original.transvar != NULL )
6947  {
6948  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6949  cliquetable, newbound) );
6950  }
6951  else
6952  {
6953  assert(set->stage == SCIP_STAGE_PROBLEM);
6954  if( newbound > SCIPvarGetLbLocal(var) )
6955  {
6956  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6957  }
6958  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6959  }
6960  break;
6961 
6962  case SCIP_VARSTATUS_COLUMN:
6963  case SCIP_VARSTATUS_LOOSE:
6964  if( newbound > SCIPvarGetLbLocal(var) )
6965  {
6966  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6967  }
6968  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6969  break;
6970 
6971  case SCIP_VARSTATUS_FIXED:
6972  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6973  return SCIP_INVALIDDATA;
6974 
6975  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6976  assert(var->data.aggregate.var != NULL);
6977  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6978  {
6979  SCIP_Real childnewbound;
6980 
6981  /* a > 0 -> change lower bound of y */
6982  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6983  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6985  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6986  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6987  else
6988  childnewbound = newbound;
6989  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6990  childnewbound) );
6991  }
6992  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6993  {
6994  SCIP_Real childnewbound;
6995 
6996  /* a < 0 -> change upper bound of y */
6997  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6998  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7000  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7001  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7002  else
7003  childnewbound = -newbound;
7004  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7005  childnewbound) );
7006  }
7007  else
7008  {
7009  SCIPerrorMessage("scalar is zero in aggregation\n");
7010  return SCIP_INVALIDDATA;
7011  }
7012  break;
7013 
7015  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7016  return SCIP_INVALIDDATA;
7017 
7018  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7019  assert(var->negatedvar != NULL);
7021  assert(var->negatedvar->negatedvar == var);
7022  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7023  var->data.negate.constant - newbound) );
7024  break;
7025 
7026  default:
7027  SCIPerrorMessage("unknown variable status\n");
7028  return SCIP_INVALIDDATA;
7029  }
7030 
7031  return SCIP_OKAY;
7032 }
7033 
7034 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7035  * updates local upper bound if the global bound is tighter
7036  */
7038  SCIP_VAR* var, /**< problem variable to change */
7039  BMS_BLKMEM* blkmem, /**< block memory */
7040  SCIP_SET* set, /**< global SCIP settings */
7041  SCIP_STAT* stat, /**< problem statistics */
7042  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7043  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7044  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7045  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7046  SCIP_Real newbound /**< new bound for variable */
7047  )
7048 {
7049  assert(var != NULL);
7050  assert(blkmem != NULL);
7051  assert(set != NULL);
7052  assert(var->scip == set->scip);
7053 
7054  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7055  * of the domain within feastol
7056  */
7057  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7058 
7059  /* adjust bound to integral value if variable is of integral type */
7060  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7061 
7062  /* check that the adjusted bound is feasible
7063  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7064  * here because we reset bounds to their original value!
7065  */
7066  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7067 
7068  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7069  {
7070  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7071  newbound = MAX(newbound, var->glbdom.lb);
7072  }
7073  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7074 
7075  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7076  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7077  */
7078  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7079 
7080  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7081 
7082  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
7083  return SCIP_OKAY;
7084 
7085  /* change bounds of attached variables */
7086  switch( SCIPvarGetStatus(var) )
7087  {
7089  if( var->data.original.transvar != NULL )
7090  {
7091  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7092  newbound) );
7093  }
7094  else
7095  {
7096  assert(set->stage == SCIP_STAGE_PROBLEM);
7097  if( newbound < SCIPvarGetUbLocal(var) )
7098  {
7099  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7100  }
7101  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7102  }
7103  break;
7104 
7105  case SCIP_VARSTATUS_COLUMN:
7106  case SCIP_VARSTATUS_LOOSE:
7107  if( newbound < SCIPvarGetUbLocal(var) )
7108  {
7109  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7110  }
7111  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7112  break;
7113 
7114  case SCIP_VARSTATUS_FIXED:
7115  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7116  return SCIP_INVALIDDATA;
7117 
7118  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7119  assert(var->data.aggregate.var != NULL);
7120  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7121  {
7122  SCIP_Real childnewbound;
7123 
7124  /* a > 0 -> change lower bound of y */
7125  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7126  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7128  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7129  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7130  else
7131  childnewbound = newbound;
7132  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7133  childnewbound) );
7134  }
7135  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7136  {
7137  SCIP_Real childnewbound;
7138 
7139  /* a < 0 -> change upper bound of y */
7140  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7141  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7143  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7144  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7145  else
7146  childnewbound = -newbound;
7147  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7148  childnewbound) );
7149  }
7150  else
7151  {
7152  SCIPerrorMessage("scalar is zero in aggregation\n");
7153  return SCIP_INVALIDDATA;
7154  }
7155  break;
7156 
7158  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7159  return SCIP_INVALIDDATA;
7160 
7161  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7162  assert(var->negatedvar != NULL);
7164  assert(var->negatedvar->negatedvar == var);
7165  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7166  var->data.negate.constant - newbound) );
7167  break;
7168 
7169  default:
7170  SCIPerrorMessage("unknown variable status\n");
7171  return SCIP_INVALIDDATA;
7172  }
7173 
7174  return SCIP_OKAY;
7175 }
7176 
7177 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7179  SCIP_VAR* var, /**< problem variable */
7180  SCIP_SET* set, /**< global SCIP settings */
7181  SCIP_Real lazylb /**< the lazy lower bound to be set */
7182  )
7183 {
7184  assert(var != NULL);
7185  assert(var->probindex != -1);
7186  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7187  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7188  assert(set != NULL);
7189  assert(var->scip == set->scip);
7190 
7191  /* variable should not be in the LP */
7193  return SCIP_INVALIDCALL;
7194 
7195  var->lazylb = lazylb;
7196 
7197  return SCIP_OKAY;
7198 }
7199 
7200 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7202  SCIP_VAR* var, /**< problem variable */
7203  SCIP_SET* set, /**< global SCIP settings */
7204  SCIP_Real lazyub /**< the lazy lower bound to be set */
7205  )
7206 {
7207  assert(var != NULL);
7208  assert(var->probindex != -1);
7209  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7210  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7211  assert(set != NULL);
7212  assert(var->scip == set->scip);
7213 
7214  /* variable should not be in the LP */
7216  return SCIP_INVALIDCALL;
7217 
7218  var->lazyub = lazyub;
7219 
7220  return SCIP_OKAY;
7221 }
7222 
7223 
7224 /** changes global bound of variable; if possible, adjusts bound to integral value;
7225  * updates local bound if the global bound is tighter
7226  */
7228  SCIP_VAR* var, /**< problem variable to change */
7229  BMS_BLKMEM* blkmem, /**< block memory */
7230  SCIP_SET* set, /**< global SCIP settings */
7231  SCIP_STAT* stat, /**< problem statistics */
7232  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7233  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7234  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7235  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7236  SCIP_Real newbound, /**< new bound for variable */
7237  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7238  )
7239 {
7240  /* apply bound change to the LP data */
7241  switch( boundtype )
7242  {
7243  case SCIP_BOUNDTYPE_LOWER:
7244  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7245  case SCIP_BOUNDTYPE_UPPER:
7246  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7247  default:
7248  SCIPerrorMessage("unknown bound type\n");
7249  return SCIP_INVALIDDATA;
7250  }
7251 }
7252 
7253 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7254 static
7256  SCIP_VAR* var, /**< problem variable to change */
7257  BMS_BLKMEM* blkmem, /**< block memory */
7258  SCIP_SET* set, /**< global SCIP settings */
7259  SCIP_LP* lp, /**< current LP data */
7260  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7261  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7262  SCIP_Real oldbound, /**< old lower bound for variable */
7263  SCIP_Real newbound /**< new lower bound for variable */
7264  )
7265 {
7266  assert(var != NULL);
7267  assert(var->eventfilter != NULL);
7268  assert(SCIPvarIsTransformed(var));
7269  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb); /*lint !e777*/
7270  assert(set != NULL);
7271  assert(var->scip == set->scip);
7272 
7273  /* check, if the variable is being tracked for bound changes
7274  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7275  */
7276  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7279  {
7280  SCIP_EVENT* event;
7281 
7282  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7283 
7284  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7285  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7286  }
7287 
7288  return SCIP_OKAY;
7289 }
7290 
7291 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
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_LP* lp, /**< current LP data */
7298  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7299  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7300  SCIP_Real oldbound, /**< old upper bound for variable */
7301  SCIP_Real newbound /**< new upper bound for variable */
7302  )
7303 {
7304  assert(var != NULL);
7305  assert(var->eventfilter != NULL);
7306  assert(SCIPvarIsTransformed(var));
7307  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub); /*lint !e777*/
7308  assert(set != NULL);
7309  assert(var->scip == set->scip);
7310 
7311  /* check, if the variable is being tracked for bound changes
7312  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7313  */
7314  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7317  {
7318  SCIP_EVENT* event;
7319 
7320  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7321 
7322  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7323  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7324  }
7325 
7326  return SCIP_OKAY;
7327 }
7328 
7329 /* forward declaration, because both methods call each other recursively */
7330 
7331 /* performs the current change in upper bound, changes all parents accordingly */
7332 static
7334  SCIP_VAR* var, /**< problem variable to change */
7335  BMS_BLKMEM* blkmem, /**< block memory */
7336  SCIP_SET* set, /**< global SCIP settings */
7337  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7338  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7339  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7340  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7341  SCIP_Real newbound /**< new bound for variable */
7342  );
7343 
7344 /** performs the current change in lower bound, changes all parents accordingly */
7345 static
7347  SCIP_VAR* var, /**< problem variable to change */
7348  BMS_BLKMEM* blkmem, /**< block memory */
7349  SCIP_SET* set, /**< global SCIP settings */
7350  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7351  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7352  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7353  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7354  SCIP_Real newbound /**< new bound for variable */
7355  )
7356 {
7357  SCIP_VAR* parentvar;
7358  SCIP_Real oldbound;
7359  int i;
7360 
7361  assert(var != NULL);
7362  assert(set != NULL);
7363  assert(var->scip == set->scip);
7364  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7365  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7366  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7367  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7369 
7370  /* check that the bound is feasible */
7371  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7372  /* adjust bound to integral value if variable is of integral type */
7373  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7374 
7375  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7376  {
7377  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7378  newbound = MIN(newbound, var->locdom.ub);
7379 
7380  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7381  newbound = MAX(newbound, var->glbdom.lb);
7382  }
7383  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7384 
7385  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7386 
7387  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7388  newbound = var->glbdom.lb;
7389  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7390  return SCIP_OKAY;
7391 
7392  /* change the bound */
7393  oldbound = var->locdom.lb;
7394  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7395  var->locdom.lb = newbound;
7396 
7397  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7398  * once update the statistic
7399  */
7400  if( stat != NULL )
7401  SCIPstatIncrement(stat, set, domchgcount);
7402 
7403  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7404  {
7405  /* merges overlapping holes into single holes, moves bounds respectively */
7406  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7407  }
7408 
7409  /* issue bound change event */
7410  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7411  if( var->eventfilter != NULL )
7412  {
7413  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7414  }
7415 
7416  /* process parent variables */
7417  for( i = 0; i < var->nparentvars; ++i )
7418  {
7419  parentvar = var->parentvars[i];
7420  assert(parentvar != NULL);
7421 
7422  switch( SCIPvarGetStatus(parentvar) )
7423  {
7425  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7426  break;
7427 
7428  case SCIP_VARSTATUS_COLUMN:
7429  case SCIP_VARSTATUS_LOOSE:
7430  case SCIP_VARSTATUS_FIXED:
7432  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7433  return SCIP_INVALIDDATA;
7434 
7435  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7436  assert(parentvar->data.aggregate.var == var);
7437  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7438  {
7439  SCIP_Real parentnewbound;
7440 
7441  /* a > 0 -> change lower bound of y */
7442  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7443  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7444  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7445 
7446  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7447  {
7448  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7449  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7450  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7451  * as a result, the parent's lower bound is set to it's upper bound, and not above
7452  */
7453  if( parentnewbound > parentvar->glbdom.ub )
7454  {
7455  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7456  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7457  parentnewbound = parentvar->glbdom.ub;
7458  }
7459  }
7460  else
7461  parentnewbound = newbound;
7462  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7463  }
7464  else
7465  {
7466  SCIP_Real parentnewbound;
7467 
7468  /* a < 0 -> change upper bound of y */
7469  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7470  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7471  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7472  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7473 
7474  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7475  {
7476  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7477  /* 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
7478  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7479  * as a result, the parent's upper bound is set to it's lower bound, and not below
7480  */
7481  if( parentnewbound < parentvar->glbdom.lb )
7482  {
7483  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7484  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7485  parentnewbound = parentvar->glbdom.lb;
7486  }
7487  }
7488  else
7489  parentnewbound = -newbound;
7490  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7491  }
7492  break;
7493 
7494  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7495  assert(parentvar->negatedvar != NULL);
7496  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7497  assert(parentvar->negatedvar->negatedvar == parentvar);
7498  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7499  parentvar->data.negate.constant - newbound) );
7500  break;
7501 
7502  default:
7503  SCIPerrorMessage("unknown variable status\n");
7504  return SCIP_INVALIDDATA;
7505  }
7506  }
7507 
7508  return SCIP_OKAY;
7509 }
7510 
7511 /** performs the current change in upper bound, changes all parents accordingly */
7512 static
7514  SCIP_VAR* var, /**< problem variable to change */
7515  BMS_BLKMEM* blkmem, /**< block memory */
7516  SCIP_SET* set, /**< global SCIP settings */
7517  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7518  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7519  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7520  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7521  SCIP_Real newbound /**< new bound for variable */
7522  )
7523 {
7524  SCIP_VAR* parentvar;
7525  SCIP_Real oldbound;
7526  int i;
7527 
7528  assert(var != NULL);
7529  assert(set != NULL);
7530  assert(var->scip == set->scip);
7531  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7532  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7533  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7534  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7536 
7537  /* check that the bound is feasible */
7538  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7539  /* adjust bound to integral value if variable is of integral type */
7540  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7541 
7542  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7543  {
7544  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7545  newbound = MAX(newbound, var->locdom.lb);
7546 
7547  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7548  newbound = MIN(newbound, var->glbdom.ub);
7549  }
7550  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7551 
7552  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7553 
7554  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7555  newbound = var->glbdom.ub;
7556  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7557  return SCIP_OKAY;
7558 
7559  /* change the bound */
7560  oldbound = var->locdom.ub;
7561  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7562  var->locdom.ub = newbound;
7563 
7564  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7565  * once update the statistic
7566  */
7567  if( stat != NULL )
7568  SCIPstatIncrement(stat, set, domchgcount);
7569 
7570  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7571  {
7572  /* merges overlapping holes into single holes, moves bounds respectively */
7573  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7574  }
7575 
7576  /* issue bound change event */
7577  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7578  if( var->eventfilter != NULL )
7579  {
7580  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7581  }
7582 
7583  /* process parent variables */
7584  for( i = 0; i < var->nparentvars; ++i )
7585  {
7586  parentvar = var->parentvars[i];
7587  assert(parentvar != NULL);
7588 
7589  switch( SCIPvarGetStatus(parentvar) )
7590  {
7592  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7593  break;
7594 
7595  case SCIP_VARSTATUS_COLUMN:
7596  case SCIP_VARSTATUS_LOOSE:
7597  case SCIP_VARSTATUS_FIXED:
7599  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7600  return SCIP_INVALIDDATA;
7601 
7602  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7603  assert(parentvar->data.aggregate.var == var);
7604  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7605  {
7606  SCIP_Real parentnewbound;
7607 
7608  /* a > 0 -> change upper bound of x */
7609  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7610  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7611  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7612  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7613  {
7614  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7615  /* 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
7616  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7617  * as a result, the parent's upper bound is set to it's lower bound, and not below
7618  */
7619  if( parentnewbound < parentvar->glbdom.lb )
7620  {
7621  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7622  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7623  parentnewbound = parentvar->glbdom.lb;
7624  }
7625  }
7626  else
7627  parentnewbound = newbound;
7628  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7629  }
7630  else
7631  {
7632  SCIP_Real parentnewbound;
7633 
7634  /* a < 0 -> change lower bound of x */
7635  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7636  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7637  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7638  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7639  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7640  {
7641  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7642  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7643  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7644  * as a result, the parent's lower bound is set to it's upper bound, and not above
7645  */
7646  if( parentnewbound > parentvar->glbdom.ub )
7647  {
7648  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7649  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7650  parentnewbound = parentvar->glbdom.ub;
7651  }
7652  }
7653  else
7654  parentnewbound = -newbound;
7655  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7656  }
7657  break;
7658 
7659  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7660  assert(parentvar->negatedvar != NULL);
7661  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7662  assert(parentvar->negatedvar->negatedvar == parentvar);
7663  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7664  parentvar->data.negate.constant - newbound) );
7665  break;
7666 
7667  default:
7668  SCIPerrorMessage("unknown variable status\n");
7669  return SCIP_INVALIDDATA;
7670  }
7671  }
7672 
7673  return SCIP_OKAY;
7674 }
7675 
7676 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7677  * information in variable
7678  */
7680  SCIP_VAR* var, /**< problem variable to change */
7681  BMS_BLKMEM* blkmem, /**< block memory */
7682  SCIP_SET* set, /**< global SCIP settings */
7683  SCIP_STAT* stat, /**< problem statistics */
7684  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7685  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7686  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7687  SCIP_Real newbound /**< new bound for variable */
7688  )
7689 {
7690  assert(var != NULL);
7691  assert(blkmem != NULL);
7692  assert(set != NULL);
7693  assert(var->scip == set->scip);
7694 
7695  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7696  * of the domain within feastol
7697  */
7698  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7699 
7700  /* adjust bound to integral value if variable is of integral type */
7701  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7702 
7703  /* check that the adjusted bound is feasible */
7704  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7705 
7706  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7707  {
7708  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7709  newbound = MIN(newbound, var->locdom.ub);
7710  }
7711  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7712 
7713  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7714 
7715  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) ) /*lint !e777*/
7716  return SCIP_OKAY;
7717 
7718  /* change bounds of attached variables */
7719  switch( SCIPvarGetStatus(var) )
7720  {
7722  if( var->data.original.transvar != NULL )
7723  {
7724  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7725  newbound) );
7726  }
7727  else
7728  {
7729  assert(set->stage == SCIP_STAGE_PROBLEM);
7730  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7731  }
7732  break;
7733 
7734  case SCIP_VARSTATUS_COLUMN:
7735  case SCIP_VARSTATUS_LOOSE:
7736  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7737  break;
7738 
7739  case SCIP_VARSTATUS_FIXED:
7740  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7741  return SCIP_INVALIDDATA;
7742 
7743  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7744  assert(var->data.aggregate.var != NULL);
7745  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7746  {
7747  SCIP_Real childnewbound;
7748 
7749  /* a > 0 -> change lower bound of y */
7750  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7751  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7753  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7754  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7755  else
7756  childnewbound = newbound;
7757  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7758  childnewbound) );
7759  }
7760  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7761  {
7762  SCIP_Real childnewbound;
7763 
7764  /* a < 0 -> change upper bound of y */
7765  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7766  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7768  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7769  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7770  else
7771  childnewbound = -newbound;
7772  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7773  childnewbound) );
7774  }
7775  else
7776  {
7777  SCIPerrorMessage("scalar is zero in aggregation\n");
7778  return SCIP_INVALIDDATA;
7779  }
7780  break;
7781 
7783  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7784  return SCIP_INVALIDDATA;
7785 
7786  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7787  assert(var->negatedvar != NULL);
7789  assert(var->negatedvar->negatedvar == var);
7790  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7791  var->data.negate.constant - newbound) );
7792  break;
7793 
7794  default:
7795  SCIPerrorMessage("unknown variable status\n");
7796  return SCIP_INVALIDDATA;
7797  }
7798 
7799  return SCIP_OKAY;
7800 }
7801 
7802 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7803  * information in variable
7804  */
7806  SCIP_VAR* var, /**< problem variable to change */
7807  BMS_BLKMEM* blkmem, /**< block memory */
7808  SCIP_SET* set, /**< global SCIP settings */
7809  SCIP_STAT* stat, /**< problem statistics */
7810  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7811  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7812  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7813  SCIP_Real newbound /**< new bound for variable */
7814  )
7815 {
7816  assert(var != NULL);
7817  assert(blkmem != NULL);
7818  assert(set != NULL);
7819  assert(var->scip == set->scip);
7820 
7821  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7822  * of the domain within feastol
7823  */
7824  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7825 
7826  /* adjust bound to integral value if variable is of integral type */
7827  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7828 
7829  /* check that the adjusted bound is feasible */
7830  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7831 
7832  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7833  {
7834  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7835  newbound = MAX(newbound, var->locdom.lb);
7836  }
7837  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7838 
7839  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7840 
7841  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) ) /*lint !e777*/
7842  return SCIP_OKAY;
7843 
7844  /* change bounds of attached variables */
7845  switch( SCIPvarGetStatus(var) )
7846  {
7848  if( var->data.original.transvar != NULL )
7849  {
7850  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7851  }
7852  else
7853  {
7854  assert(set->stage == SCIP_STAGE_PROBLEM);
7855  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7856  }
7857  break;
7858 
7859  case SCIP_VARSTATUS_COLUMN:
7860  case SCIP_VARSTATUS_LOOSE:
7861  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7862  break;
7863 
7864  case SCIP_VARSTATUS_FIXED:
7865  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7866  return SCIP_INVALIDDATA;
7867 
7868  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7869  assert(var->data.aggregate.var != NULL);
7870  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7871  {
7872  SCIP_Real childnewbound;
7873 
7874  /* a > 0 -> change upper bound of y */
7875  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7876  || SCIPsetIsFeasEQ(set, var->locdom.ub,
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( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7883  childnewbound) );
7884  }
7885  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7886  {
7887  SCIP_Real childnewbound;
7888 
7889  /* a < 0 -> change lower bound of y */
7890  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7891  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7893  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7894  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7895  else
7896  childnewbound = -newbound;
7897  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7898  childnewbound) );
7899  }
7900  else
7901  {
7902  SCIPerrorMessage("scalar is zero in aggregation\n");
7903  return SCIP_INVALIDDATA;
7904  }
7905  break;
7906 
7908  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7909  return SCIP_INVALIDDATA;
7910 
7911  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7912  assert(var->negatedvar != NULL);
7914  assert(var->negatedvar->negatedvar == var);
7915  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7916  var->data.negate.constant - newbound) );
7917  break;
7918 
7919  default:
7920  SCIPerrorMessage("unknown variable status\n");
7921  return SCIP_INVALIDDATA;
7922  }
7923 
7924  return SCIP_OKAY;
7925 }
7926 
7927 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7928  * information in variable
7929  */
7931  SCIP_VAR* var, /**< problem variable to change */
7932  BMS_BLKMEM* blkmem, /**< block memory */
7933  SCIP_SET* set, /**< global SCIP settings */
7934  SCIP_STAT* stat, /**< problem statistics */
7935  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7936  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7937  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7938  SCIP_Real newbound, /**< new bound for variable */
7939  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7940  )
7941 {
7942  /* apply bound change to the LP data */
7943  switch( boundtype )
7944  {
7945  case SCIP_BOUNDTYPE_LOWER:
7946  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7947  case SCIP_BOUNDTYPE_UPPER:
7948  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7949  default:
7950  SCIPerrorMessage("unknown bound type\n");
7951  return SCIP_INVALIDDATA;
7952  }
7953 }
7954 
7955 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7957  SCIP_VAR* var, /**< problem variable to change */
7958  SCIP_SET* set, /**< global SCIP settings */
7959  SCIP_LP* lp, /**< current LP data */
7960  SCIP_Real newbound /**< new bound for variable */
7961  )
7962 {
7963  assert(var != NULL);
7964  assert(set != NULL);
7965  assert(var->scip == set->scip);
7966  assert(lp != NULL);
7967  assert(SCIPlpDiving(lp));
7968 
7969  /* adjust bound for integral variables */
7970  SCIPvarAdjustLb(var, set, &newbound);
7971 
7972  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7973 
7974  /* change bounds of attached variables */
7975  switch( SCIPvarGetStatus(var) )
7976  {
7978  assert(var->data.original.transvar != NULL);
7979  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7980  break;
7981 
7982  case SCIP_VARSTATUS_COLUMN:
7983  assert(var->data.col != NULL);
7984  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7985  break;
7986 
7987  case SCIP_VARSTATUS_LOOSE:
7988  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7989  return SCIP_INVALIDDATA;
7990 
7991  case SCIP_VARSTATUS_FIXED:
7992  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7993  return SCIP_INVALIDDATA;
7994 
7995  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7996  assert(var->data.aggregate.var != NULL);
7997  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7998  {
7999  SCIP_Real childnewbound;
8000 
8001  /* a > 0 -> change lower bound of y */
8002  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8003  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8004  else
8005  childnewbound = newbound;
8006  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8007  }
8008  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8009  {
8010  SCIP_Real childnewbound;
8011 
8012  /* a < 0 -> change upper bound of y */
8013  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8014  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8015  else
8016  childnewbound = -newbound;
8017  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8018  }
8019  else
8020  {
8021  SCIPerrorMessage("scalar is zero in aggregation\n");
8022  return SCIP_INVALIDDATA;
8023  }
8024  break;
8025 
8027  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8028  return SCIP_INVALIDDATA;
8029 
8030  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8031  assert(var->negatedvar != NULL);
8033  assert(var->negatedvar->negatedvar == var);
8034  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8035  break;
8036 
8037  default:
8038  SCIPerrorMessage("unknown variable status\n");
8039  return SCIP_INVALIDDATA;
8040  }
8041 
8042  return SCIP_OKAY;
8043 }
8044 
8045 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8047  SCIP_VAR* var, /**< problem variable to change */
8048  SCIP_SET* set, /**< global SCIP settings */
8049  SCIP_LP* lp, /**< current LP data */
8050  SCIP_Real newbound /**< new bound for variable */
8051  )
8052 {
8053  assert(var != NULL);
8054  assert(set != NULL);
8055  assert(var->scip == set->scip);
8056  assert(lp != NULL);
8057  assert(SCIPlpDiving(lp));
8058 
8059  /* adjust bound for integral variables */
8060  SCIPvarAdjustUb(var, set, &newbound);
8061 
8062  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8063 
8064  /* change bounds of attached variables */
8065  switch( SCIPvarGetStatus(var) )
8066  {
8068  assert(var->data.original.transvar != NULL);
8069  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8070  break;
8071 
8072  case SCIP_VARSTATUS_COLUMN:
8073  assert(var->data.col != NULL);
8074  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8075  break;
8076 
8077  case SCIP_VARSTATUS_LOOSE:
8078  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8079  return SCIP_INVALIDDATA;
8080 
8081  case SCIP_VARSTATUS_FIXED:
8082  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8083  return SCIP_INVALIDDATA;
8084 
8085  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8086  assert(var->data.aggregate.var != NULL);
8087  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8088  {
8089  SCIP_Real childnewbound;
8090 
8091  /* a > 0 -> change upper bound of y */
8092  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8093  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8094  else
8095  childnewbound = newbound;
8096  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8097  }
8098  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8099  {
8100  SCIP_Real childnewbound;
8101 
8102  /* a < 0 -> change lower bound of y */
8103  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8104  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8105  else
8106  childnewbound = -newbound;
8107  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8108  }
8109  else
8110  {
8111  SCIPerrorMessage("scalar is zero in aggregation\n");
8112  return SCIP_INVALIDDATA;
8113  }
8114  break;
8115 
8117  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8118  return SCIP_INVALIDDATA;
8119 
8120  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8121  assert(var->negatedvar != NULL);
8123  assert(var->negatedvar->negatedvar == var);
8124  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8125  break;
8126 
8127  default:
8128  SCIPerrorMessage("unknown variable status\n");
8129  return SCIP_INVALIDDATA;
8130  }
8131 
8132  return SCIP_OKAY;
8133 }
8134 
8135 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8136  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8137  * not updated if bounds of aggregation variables are changing
8138  *
8139  * calling this function for a non-multi-aggregated variable is not allowed
8140  */
8142  SCIP_VAR* var, /**< problem variable */
8143  SCIP_SET* set /**< global SCIP settings */
8144  )
8145 {
8146  int i;
8147  SCIP_Real lb;
8148  SCIP_Real bnd;
8149  SCIP_VAR* aggrvar;
8150  SCIP_Bool posinf;
8151  SCIP_Bool neginf;
8152 
8153  assert(var != NULL);
8154  assert(set != NULL);
8155  assert(var->scip == set->scip);
8157 
8158  posinf = FALSE;
8159  neginf = FALSE;
8160  lb = var->data.multaggr.constant;
8161  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8162  {
8163  aggrvar = var->data.multaggr.vars[i];
8164  if( var->data.multaggr.scalars[i] > 0.0 )
8165  {
8166  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8167 
8168  if( SCIPsetIsInfinity(set, bnd) )
8169  posinf = TRUE;
8170  else if( SCIPsetIsInfinity(set, -bnd) )
8171  neginf = TRUE;
8172  else
8173  lb += var->data.multaggr.scalars[i] * bnd;
8174  }
8175  else
8176  {
8177  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8178 
8179  if( SCIPsetIsInfinity(set, -bnd) )
8180  posinf = TRUE;
8181  else if( SCIPsetIsInfinity(set, bnd) )
8182  neginf = TRUE;
8183  else
8184  lb += var->data.multaggr.scalars[i] * bnd;
8185  }
8186 
8187  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8188  * variable
8189  */
8190  if( neginf )
8191  return SCIPvarGetLbLocal(var);
8192  }
8193 
8194  /* if positive infinity flag was set to true return infinity */
8195  if( posinf )
8196  return SCIPsetInfinity(set);
8197 
8198  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8199 }
8200 
8201 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8202  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8203  * not updated if bounds of aggregation variables are changing
8204  *
8205  * calling this function for a non-multi-aggregated variable is not allowed
8206  */
8208  SCIP_VAR* var, /**< problem variable */
8209  SCIP_SET* set /**< global SCIP settings */
8210  )
8211 {
8212  int i;
8213  SCIP_Real ub;
8214  SCIP_Real bnd;
8215  SCIP_VAR* aggrvar;
8216  SCIP_Bool posinf;
8217  SCIP_Bool neginf;
8218 
8219  assert(var != NULL);
8220  assert(set != NULL);
8221  assert(var->scip == set->scip);
8223 
8224  posinf = FALSE;
8225  neginf = FALSE;
8226  ub = var->data.multaggr.constant;
8227  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8228  {
8229  aggrvar = var->data.multaggr.vars[i];
8230  if( var->data.multaggr.scalars[i] > 0.0 )
8231  {
8232  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8233 
8234  if( SCIPsetIsInfinity(set, bnd) )
8235  posinf = TRUE;
8236  else if( SCIPsetIsInfinity(set, -bnd) )
8237  neginf = TRUE;
8238  else
8239  ub += var->data.multaggr.scalars[i] * bnd;
8240  }
8241  else
8242  {
8243  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8244 
8245  if( SCIPsetIsInfinity(set, -bnd) )
8246  posinf = TRUE;
8247  else if( SCIPsetIsInfinity(set, bnd) )
8248  neginf = TRUE;
8249  else
8250  ub += var->data.multaggr.scalars[i] * bnd;
8251  }
8252 
8253  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8254  * variable
8255  */
8256  if( posinf )
8257  return SCIPvarGetUbLocal(var);
8258  }
8259 
8260  /* if negative infinity flag was set to true return -infinity */
8261  if( neginf )
8262  return -SCIPsetInfinity(set);
8263 
8264  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8265 }
8266 
8267 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8268  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8269  * not updated if bounds of aggregation variables are changing
8270  *
8271  * calling this function for a non-multi-aggregated variable is not allowed
8272  */
8274  SCIP_VAR* var, /**< problem variable */
8275  SCIP_SET* set /**< global SCIP settings */
8276  )
8277 {
8278  int i;
8279  SCIP_Real lb;
8280  SCIP_Real bnd;
8281  SCIP_VAR* aggrvar;
8282  SCIP_Bool posinf;
8283  SCIP_Bool neginf;
8284 
8285  assert(var != NULL);
8286  assert(set != NULL);
8287  assert(var->scip == set->scip);
8289 
8290  posinf = FALSE;
8291  neginf = FALSE;
8292  lb = var->data.multaggr.constant;
8293  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8294  {
8295  aggrvar = var->data.multaggr.vars[i];
8296  if( var->data.multaggr.scalars[i] > 0.0 )
8297  {
8298  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8299 
8300  if( SCIPsetIsInfinity(set, bnd) )
8301  posinf = TRUE;
8302  else if( SCIPsetIsInfinity(set, -bnd) )
8303  neginf = TRUE;
8304  else
8305  lb += var->data.multaggr.scalars[i] * bnd;
8306  }
8307  else
8308  {
8309  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8310 
8311  if( SCIPsetIsInfinity(set, -bnd) )
8312  posinf = TRUE;
8313  else if( SCIPsetIsInfinity(set, bnd) )
8314  neginf = TRUE;
8315  else
8316  lb += var->data.multaggr.scalars[i] * bnd;
8317  }
8318 
8319  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8320  * variable
8321  */
8322  if( neginf )
8323  return SCIPvarGetLbGlobal(var);
8324  }
8325 
8326  /* if positive infinity flag was set to true return infinity */
8327  if( posinf )
8328  return SCIPsetInfinity(set);
8329 
8330  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8331 }
8332 
8333 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8334  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8335  * not updated if bounds of aggregation variables are changing
8336  *
8337  * calling this function for a non-multi-aggregated variable is not allowed
8338  */
8340  SCIP_VAR* var, /**< problem variable */
8341  SCIP_SET* set /**< global SCIP settings */
8342  )
8343 {
8344  int i;
8345  SCIP_Real ub;
8346  SCIP_Real bnd;
8347  SCIP_VAR* aggrvar;
8348  SCIP_Bool posinf;
8349  SCIP_Bool neginf;
8350 
8351  assert(var != NULL);
8352  assert(set != NULL);
8353  assert(var->scip == set->scip);
8355 
8356  posinf = FALSE;
8357  neginf = FALSE;
8358  ub = var->data.multaggr.constant;
8359  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8360  {
8361  aggrvar = var->data.multaggr.vars[i];
8362  if( var->data.multaggr.scalars[i] > 0.0 )
8363  {
8364  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8365 
8366  if( SCIPsetIsInfinity(set, bnd) )
8367  posinf = TRUE;
8368  else if( SCIPsetIsInfinity(set, -bnd) )
8369  neginf = TRUE;
8370  else
8371  ub += var->data.multaggr.scalars[i] * bnd;
8372  }
8373  else
8374  {
8375  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8376 
8377  if( SCIPsetIsInfinity(set, -bnd) )
8378  posinf = TRUE;
8379  else if( SCIPsetIsInfinity(set, bnd) )
8380  neginf = TRUE;
8381  else
8382  ub += var->data.multaggr.scalars[i] * bnd;
8383  }
8384 
8385  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8386  * variable
8387  */
8388  if( posinf )
8389  return SCIPvarGetUbGlobal(var);
8390  }
8391 
8392  /* if negative infinity flag was set to true return -infinity */
8393  if( neginf )
8394  return -SCIPsetInfinity(set);
8395 
8396  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8397 }
8398 
8399 /** adds a hole to the original domain of the variable */
8401  SCIP_VAR* var, /**< problem variable */
8402  BMS_BLKMEM* blkmem, /**< block memory */
8403  SCIP_SET* set, /**< global SCIP settings */
8404  SCIP_Real left, /**< left bound of open interval in new hole */
8405  SCIP_Real right /**< right bound of open interval in new hole */
8406  )
8407 {
8408  SCIP_Bool added;
8409 
8410  assert(var != NULL);
8411  assert(!SCIPvarIsTransformed(var));
8413  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8414  assert(set != NULL);
8415  assert(var->scip == set->scip);
8416  assert(set->stage == SCIP_STAGE_PROBLEM);
8417 
8418  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8419 
8420  if( SCIPsetIsEQ(set, left, right) )
8421  return SCIP_OKAY;
8422 
8423  /* the interval should not be empty */
8424  assert(SCIPsetIsLT(set, left, right));
8425 
8426  /* the the interval bound should already be adjusted */
8427  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8428  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8429 
8430  /* the the interval should lay between the lower and upper bound */
8431  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8432  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8433 
8434  /* add domain hole */
8435  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8436 
8437  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8438  if( added )
8439  {
8440  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8441  }
8442 
8443  /**@todo add hole in parent and child variables (just like with bound changes);
8444  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8445  */
8446 
8447  return SCIP_OKAY;
8448 }
8449 
8450 /** performs the current add of domain, changes all parents accordingly */
8451 static
8453  SCIP_VAR* var, /**< problem variable */
8454  BMS_BLKMEM* blkmem, /**< block memory */
8455  SCIP_SET* set, /**< global SCIP settings */
8456  SCIP_STAT* stat, /**< problem statistics */
8457  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8458  SCIP_Real left, /**< left bound of open interval in new hole */
8459  SCIP_Real right, /**< right bound of open interval in new hole */
8460  SCIP_Bool* added /**< pointer to store whether the hole was added */
8461  )
8462 {
8463  SCIP_VAR* parentvar;
8464  SCIP_Real newlb;
8465  SCIP_Real newub;
8466  int i;
8467 
8468  assert(var != NULL);
8469  assert(added != NULL);
8470  assert(blkmem != NULL);
8471 
8472  /* the interval should not be empty */
8473  assert(SCIPsetIsLT(set, left, right));
8474 
8475  /* the interval bound should already be adjusted */
8476  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8477  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8478 
8479  /* the interval should lay between the lower and upper bound */
8480  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8481  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8482 
8483  /* @todo add debugging mechanism for holes when using a debugging solution */
8484 
8485  /* add hole to hole list */
8486  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8487 
8488  /* check if the hole is redundant */
8489  if( !(*added) )
8490  return SCIP_OKAY;
8491 
8492  /* current bounds */
8493  newlb = var->glbdom.lb;
8494  newub = var->glbdom.ub;
8495 
8496  /* merge domain holes */
8497  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8498 
8499  /* the bound should not be changed */
8500  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8501  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8502 
8503  /* issue bound change event */
8504  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8505  if( var->eventfilter != NULL )
8506  {
8507  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8508  }
8509 
8510  /* process parent variables */
8511  for( i = 0; i < var->nparentvars; ++i )
8512  {
8513  SCIP_Real parentnewleft;
8514  SCIP_Real parentnewright;
8515  SCIP_Bool localadded;
8516 
8517  parentvar = var->parentvars[i];
8518  assert(parentvar != NULL);
8519 
8520  switch( SCIPvarGetStatus(parentvar) )
8521  {
8523  parentnewleft = left;
8524  parentnewright = right;
8525  break;
8526 
8527  case SCIP_VARSTATUS_COLUMN:
8528  case SCIP_VARSTATUS_LOOSE:
8529  case SCIP_VARSTATUS_FIXED:
8531  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8532  return SCIP_INVALIDDATA;
8533 
8534  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8535  assert(parentvar->data.aggregate.var == var);
8536 
8537  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8538  {
8539  /* a > 0 -> change upper bound of x */
8540  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8541  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8542  }
8543  else
8544  {
8545  /* a < 0 -> change lower bound of x */
8546  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8547 
8548  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8549  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8550  }
8551  break;
8552 
8553  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8554  assert(parentvar->negatedvar != NULL);
8555  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8556  assert(parentvar->negatedvar->negatedvar == parentvar);
8557 
8558  parentnewright = -left + parentvar->data.negate.constant;
8559  parentnewleft = -right + parentvar->data.negate.constant;
8560  break;
8561 
8562  default:
8563  SCIPerrorMessage("unknown variable status\n");
8564  return SCIP_INVALIDDATA;
8565  }
8566 
8567  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8568 
8569  /* perform hole added for parent variable */
8570  assert(blkmem != NULL);
8571  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8572  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8573  parentnewleft, parentnewright, &localadded) );
8574  assert(localadded);
8575  }
8576 
8577  return SCIP_OKAY;
8578 }
8579 
8580 /** adds a hole to the variable's global and local domain */
8582  SCIP_VAR* var, /**< problem variable */
8583  BMS_BLKMEM* blkmem, /**< block memory */
8584  SCIP_SET* set, /**< global SCIP settings */
8585  SCIP_STAT* stat, /**< problem statistics */
8586  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8587  SCIP_Real left, /**< left bound of open interval in new hole */
8588  SCIP_Real right, /**< right bound of open interval in new hole */
8589  SCIP_Bool* added /**< pointer to store whether the hole was added */
8590  )
8591 {
8592  SCIP_Real childnewleft;
8593  SCIP_Real childnewright;
8594 
8595  assert(var != NULL);
8596  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8597  assert(blkmem != NULL);
8598  assert(added != NULL);
8599 
8600  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8601 
8602  /* the interval should not be empty */
8603  assert(SCIPsetIsLT(set, left, right));
8604 
8605  /* the the interval bound should already be adjusted */
8606  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8607  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8608 
8609  /* the the interval should lay between the lower and upper bound */
8610  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8611  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8612 
8613  /* change bounds of attached variables */
8614  switch( SCIPvarGetStatus(var) )
8615  {
8617  if( var->data.original.transvar != NULL )
8618  {
8619  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8620  left, right, added) );
8621  }
8622  else
8623  {
8624  assert(set->stage == SCIP_STAGE_PROBLEM);
8625 
8626  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8627  if( *added )
8628  {
8629  SCIP_Bool localadded;
8630 
8631  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8632  }
8633  }
8634  break;
8635 
8636  case SCIP_VARSTATUS_COLUMN:
8637  case SCIP_VARSTATUS_LOOSE:
8638  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8639  if( *added )
8640  {
8641  SCIP_Bool localadded;
8642 
8643  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8644  }
8645  break;
8646 
8647  case SCIP_VARSTATUS_FIXED:
8648  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8649  return SCIP_INVALIDDATA;
8650 
8651  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8652  assert(var->data.aggregate.var != NULL);
8653 
8654  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8655  {
8656  /* a > 0 -> change lower bound of y */
8657  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8658  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8659  }
8660  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8661  {
8662  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8663  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8664  }
8665  else
8666  {
8667  SCIPerrorMessage("scalar is zero in aggregation\n");
8668  return SCIP_INVALIDDATA;
8669  }
8670  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8671  childnewleft, childnewright, added) );
8672  break;
8673 
8675  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8676  return SCIP_INVALIDDATA;
8677 
8678  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8679  assert(var->negatedvar != NULL);
8681  assert(var->negatedvar->negatedvar == var);
8682 
8683  childnewright = -left + var->data.negate.constant;
8684  childnewleft = -right + var->data.negate.constant;
8685 
8686  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8687  childnewleft, childnewright, added) );
8688  break;
8689 
8690  default:
8691  SCIPerrorMessage("unknown variable status\n");
8692  return SCIP_INVALIDDATA;
8693  }
8694 
8695  return SCIP_OKAY;
8696 }
8697 
8698 /** performs the current add of domain, changes all parents accordingly */
8699 static
8701  SCIP_VAR* var, /**< problem variable */
8702  BMS_BLKMEM* blkmem, /**< block memory */
8703  SCIP_SET* set, /**< global SCIP settings */
8704  SCIP_STAT* stat, /**< problem statistics */
8705  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8706  SCIP_Real left, /**< left bound of open interval in new hole */
8707  SCIP_Real right, /**< right bound of open interval in new hole */
8708  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8709  )
8710 {
8711  SCIP_VAR* parentvar;
8712  SCIP_Real newlb;
8713  SCIP_Real newub;
8714  int i;
8715 
8716  assert(var != NULL);
8717  assert(added != NULL);
8718  assert(blkmem != NULL);
8719 
8720  /* the interval should not be empty */
8721  assert(SCIPsetIsLT(set, left, right));
8722 
8723  /* the the interval bound should already be adjusted */
8724  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8725  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8726 
8727  /* the the interval should lay between the lower and upper bound */
8728  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8729  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8730 
8731  /* add hole to hole list */
8732  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8733 
8734  /* check if the hole is redundant */
8735  if( !(*added) )
8736  return SCIP_OKAY;
8737 
8738  /* current bounds */
8739  newlb = var->locdom.lb;
8740  newub = var->locdom.ub;
8741 
8742  /* merge domain holes */
8743  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8744 
8745  /* the bound should not be changed */
8746  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8747  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8748 
8749 #if 0
8750  /* issue bound change event */
8751  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8752  if( var->eventfilter != NULL )
8753  {
8754  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8755  }
8756 #endif
8757 
8758  /* process parent variables */
8759  for( i = 0; i < var->nparentvars; ++i )
8760  {
8761  SCIP_Real parentnewleft;
8762  SCIP_Real parentnewright;
8763  SCIP_Bool localadded;
8764 
8765  parentvar = var->parentvars[i];
8766  assert(parentvar != NULL);
8767 
8768  switch( SCIPvarGetStatus(parentvar) )
8769  {
8771  parentnewleft = left;
8772  parentnewright = right;
8773  break;
8774 
8775  case SCIP_VARSTATUS_COLUMN:
8776  case SCIP_VARSTATUS_LOOSE:
8777  case SCIP_VARSTATUS_FIXED:
8779  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8780  return SCIP_INVALIDDATA;
8781 
8782  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8783  assert(parentvar->data.aggregate.var == var);
8784 
8785  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8786  {
8787  /* a > 0 -> change upper bound of x */
8788  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8789  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8790  }
8791  else
8792  {
8793  /* a < 0 -> change lower bound of x */
8794  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8795 
8796  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8797  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8798  }
8799  break;
8800 
8801  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8802  assert(parentvar->negatedvar != NULL);
8803  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8804  assert(parentvar->negatedvar->negatedvar == parentvar);
8805 
8806  parentnewright = -left + parentvar->data.negate.constant;
8807  parentnewleft = -right + parentvar->data.negate.constant;
8808  break;
8809 
8810  default:
8811  SCIPerrorMessage("unknown variable status\n");
8812  return SCIP_INVALIDDATA;
8813  }
8814 
8815  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8816 
8817  /* perform hole added for parent variable */
8818  assert(blkmem != NULL);
8819  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8820  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8821  parentnewleft, parentnewright, &localadded) );
8822  assert(localadded);
8823  }
8824 
8825  return SCIP_OKAY;
8826 }
8827 
8828 /** adds a hole to the variable's current local domain */
8830  SCIP_VAR* var, /**< problem variable */
8831  BMS_BLKMEM* blkmem, /**< block memory */
8832  SCIP_SET* set, /**< global SCIP settings */
8833  SCIP_STAT* stat, /**< problem statistics */
8834  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8835  SCIP_Real left, /**< left bound of open interval in new hole */
8836  SCIP_Real right, /**< right bound of open interval in new hole */
8837  SCIP_Bool* added /**< pointer to store whether the hole was added */
8838  )
8839 {
8840  SCIP_Real childnewleft;
8841  SCIP_Real childnewright;
8842 
8843  assert(var != NULL);
8844 
8845  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8846 
8847  assert(set != NULL);
8848  assert(var->scip == set->scip);
8849  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8850  assert(blkmem != NULL);
8851  assert(added != NULL);
8852 
8853  /* the interval should not be empty */
8854  assert(SCIPsetIsLT(set, left, right));
8855 
8856  /* the the interval bound should already be adjusted */
8857  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8858  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8859 
8860  /* the the interval should lay between the lower and upper bound */
8861  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8862  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8863 
8864  /* change bounds of attached variables */
8865  switch( SCIPvarGetStatus(var) )
8866  {
8868  if( var->data.original.transvar != NULL )
8869  {
8870  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8871  left, right, added) );
8872  }
8873  else
8874  {
8875  assert(set->stage == SCIP_STAGE_PROBLEM);
8876  SCIPstatIncrement(stat, set, domchgcount);
8877  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8878  }
8879  break;
8880 
8881  case SCIP_VARSTATUS_COLUMN:
8882  case SCIP_VARSTATUS_LOOSE:
8883  SCIPstatIncrement(stat, set, domchgcount);
8884  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8885  break;
8886 
8887  case SCIP_VARSTATUS_FIXED:
8888  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8889  return SCIP_INVALIDDATA;
8890 
8891  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8892  assert(var->data.aggregate.var != NULL);
8893 
8894  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8895  {
8896  /* a > 0 -> change lower bound of y */
8897  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8898  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8899  }
8900  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8901  {
8902  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8903  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8904  }
8905  else
8906  {
8907  SCIPerrorMessage("scalar is zero in aggregation\n");
8908  return SCIP_INVALIDDATA;
8909  }
8910  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8911  childnewleft, childnewright, added) );
8912  break;
8913 
8915  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8916  return SCIP_INVALIDDATA;
8917 
8918  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8919  assert(var->negatedvar != NULL);
8921  assert(var->negatedvar->negatedvar == var);
8922 
8923  childnewright = -left + var->data.negate.constant;
8924  childnewleft = -right + var->data.negate.constant;
8925 
8926  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8927  break;
8928 
8929  default:
8930  SCIPerrorMessage("unknown variable status\n");
8931  return SCIP_INVALIDDATA;
8932  }
8933 
8934  return SCIP_OKAY;
8935 }
8936 
8937 /** resets the global and local bounds of original variable to their original values */
8939  SCIP_VAR* var, /**< problem variable */
8940  BMS_BLKMEM* blkmem, /**< block memory */
8941  SCIP_SET* set, /**< global SCIP settings */
8942  SCIP_STAT* stat /**< problem statistics */
8943  )
8944 {
8945  assert(var != NULL);
8946  assert(set != NULL);
8947  assert(var->scip == set->scip);
8948  assert(SCIPvarIsOriginal(var));
8949  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8950  * the transformed variable has been fixed */
8951  assert(SCIPvarGetTransVar(var) == NULL);
8952 
8953  /* copy the original bounds back to the global and local bounds */
8954  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8955  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8956  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8957  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8958 
8959  /* free the global and local holelists and duplicate the original ones */
8960  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8961  holelistFree(&var->glbdom.holelist, blkmem);
8962  holelistFree(&var->locdom.holelist, blkmem);
8963  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8964  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8965 
8966  return SCIP_OKAY;
8967 }
8968 
8969 /** issues a IMPLADDED event on the given variable */
8970 static
8972  SCIP_VAR* var, /**< problem variable to change */
8973  BMS_BLKMEM* blkmem, /**< block memory */
8974  SCIP_SET* set, /**< global SCIP settings */
8975  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8976  )
8977 {
8978  SCIP_EVENT* event;
8979 
8980  assert(var != NULL);
8981 
8982  /* issue IMPLADDED event on variable */
8983  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8984  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8985 
8986  return SCIP_OKAY;
8987 }
8988 
8989 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8990 static
8992  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8993  BMS_BLKMEM* blkmem, /**< block memory */
8994  SCIP_SET* set, /**< global SCIP settings */
8995  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8996  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8997  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8998  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8999  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9000  )
9001 {
9002  SCIP_Bool added;
9003 
9004  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9005  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9006  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9007  *
9008  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9009  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9010  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9011  * variable bound can be ignored.
9012  *
9013  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9014  * equivalence of the variables should be checked here.
9015  */
9016  if( var == vbvar )
9017  {
9018  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9019  * can be checked via the global bounds of the variable */
9020 #ifndef NDEBUG
9021  SCIP_Real lb;
9022  SCIP_Real ub;
9023 
9024  lb = SCIPvarGetLbGlobal(var);
9025  ub = SCIPvarGetUbGlobal(var);
9026 
9027  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9028  {
9029  if( vbcoef > 0.0 )
9030  {
9031  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9032  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9033  }
9034  else
9035  {
9036  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9037  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9038  }
9039  }
9040  else
9041  {
9042  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9043  if( vbcoef > 0.0 )
9044  {
9045  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9046  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9047  }
9048  else
9049  {
9050  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9051  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9052  }
9053  }
9054 #endif
9055  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9056  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9057 
9058  return SCIP_OKAY;
9059  }
9060 
9061  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9062  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9063 
9064  /* check variable bound on debugging solution */
9065  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9066 
9067  /* perform the addition */
9068  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9069  {
9070  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9071  }
9072  else
9073  {
9074  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9075  }
9076  var->closestvblpcount = -1;
9077 
9078  if( added )
9079  {
9080  /* issue IMPLADDED event */
9081  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9082  }
9083 
9084  return SCIP_OKAY;
9085 }
9086 
9087 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9088 static
9089 void checkImplic(
9090  SCIP_SET* set, /**< global SCIP settings */
9091  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9092  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9093  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9094  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9095  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9096  )
9097 {
9098  SCIP_Real impllb;
9099  SCIP_Real implub;
9100 
9101  assert(redundant != NULL);
9102  assert(infeasible != NULL);
9103 
9104  impllb = SCIPvarGetLbGlobal(implvar);
9105  implub = SCIPvarGetUbGlobal(implvar);
9106  if( impltype == SCIP_BOUNDTYPE_LOWER )
9107  {
9108  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9109  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9110  }
9111  else
9112  {
9113  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9114  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9115  }
9116 }
9117 
9118 /** applies the given implication, if it is not redundant */
9119 static
9121  BMS_BLKMEM* blkmem, /**< block memory */
9122  SCIP_SET* set, /**< global SCIP settings */
9123  SCIP_STAT* stat, /**< problem statistics */
9124  SCIP_PROB* transprob, /**< transformed problem */
9125  SCIP_PROB* origprob, /**< original problem */
9126  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9127  SCIP_REOPT* reopt, /**< reoptimization data structure */
9128  SCIP_LP* lp, /**< current LP data */
9129  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9130  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9131  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9132  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9133  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9134  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9135  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9136  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9137  )
9138 {
9139  SCIP_Real implub;
9140  SCIP_Real impllb;
9141 
9142  assert(infeasible != NULL);
9143 
9144  *infeasible = FALSE;
9145 
9146  implub = SCIPvarGetUbGlobal(implvar);
9147  impllb = SCIPvarGetLbGlobal(implvar);
9148  if( impltype == SCIP_BOUNDTYPE_LOWER )
9149  {
9150  if( SCIPsetIsFeasGT(set, implbound, implub) )
9151  {
9152  /* the implication produces a conflict: the problem is infeasible */
9153  *infeasible = TRUE;
9154  }
9155  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9156  {
9157  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9158  * with the local bound, in this case we need to store the bound change as pending bound change
9159  */
9160  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9161  {
9162  assert(tree != NULL);
9163  assert(transprob != NULL);
9164  assert(SCIPprobIsTransformed(transprob));
9165 
9166  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9167  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9168  }
9169  else
9170  {
9171  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9172  }
9173 
9174  if( nbdchgs != NULL )
9175  (*nbdchgs)++;
9176  }
9177  }
9178  else
9179  {
9180  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9181  {
9182  /* the implication produces a conflict: the problem is infeasible */
9183  *infeasible = TRUE;
9184  }
9185  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9186  {
9187  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9188  * with the local bound, in this case we need to store the bound change as pending bound change
9189  */
9190  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9191  {
9192  assert(tree != NULL);
9193  assert(transprob != NULL);
9194  assert(SCIPprobIsTransformed(transprob));
9195 
9196  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9197  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9198  }
9199  else
9200  {
9201  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9202  }
9203 
9204  if( nbdchgs != NULL )
9205  (*nbdchgs)++;
9206  }
9207  }
9208 
9209  return SCIP_OKAY;
9210 }
9211 
9212 /** actually performs the addition of an implication to the variable's implication arrays,
9213  * and adds the corresponding implication or variable bound to the implied variable;
9214  * if the implication is conflicting, the variable is fixed to the opposite value;
9215  * if the variable is already fixed to the given value, the implication is performed immediately;
9216  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9217  */
9218 static
9220  SCIP_VAR* var, /**< problem variable */
9221  BMS_BLKMEM* blkmem, /**< block memory */
9222  SCIP_SET* set, /**< global SCIP settings */
9223  SCIP_STAT* stat, /**< problem statistics */
9224  SCIP_PROB* transprob, /**< transformed problem */
9225  SCIP_PROB* origprob, /**< original problem */
9226  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9227  SCIP_REOPT* reopt, /**< reoptimization data structure */
9228  SCIP_LP* lp, /**< current LP data */
9229  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9230  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9231  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9232  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9233  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9234  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9235  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9236  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9237  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9238  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9239  SCIP_Bool* added /**< pointer to store whether an implication was added */
9240  )
9241 {
9242  SCIP_Bool redundant;
9243  SCIP_Bool conflict;
9244 
9245  assert(var != NULL);
9246  assert(SCIPvarIsActive(var));
9248  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9249  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9250  assert(infeasible != NULL);
9251  assert(added != NULL);
9252 
9253  /* check implication on debugging solution */
9254  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9255 
9256  *infeasible = FALSE;
9257  *added = FALSE;
9258 
9259  /* check, if the implication is redundant or infeasible */
9260  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9261  assert(!redundant || !conflict);
9262  if( redundant )
9263  return SCIP_OKAY;
9264 
9265  if( var == implvar )
9266  {
9267  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9268  * x == varfixing => x < 0 or x > 1
9269  */
9270  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9271  conflict = TRUE;
9272  else
9273  {
9274  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9275  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9276  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9277  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9278  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9279  if( !conflict )
9280  return SCIP_OKAY;
9281  }
9282  }
9283 
9284  /* check, if the variable is already fixed */
9285  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9286  {
9287  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9288  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9289  {
9290  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9291  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9292  }
9293  return SCIP_OKAY;
9294  }
9295 
9296  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9297  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9298 
9299  if( !conflict )
9300  {
9301  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9302 
9303  if( SCIPvarIsBinary(implvar) )
9304  {
9305  SCIP_VAR* vars[2];
9306  SCIP_Bool vals[2];
9307 
9308  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9309  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9310 
9311  vars[0] = var;
9312  vars[1] = implvar;
9313  vals[0] = varfixing;
9314  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9315 
9316  /* add the clique to the clique table */
9317  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9318  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9319 
9320  if( !conflict )
9321  return SCIP_OKAY;
9322  }
9323  else
9324  {
9325  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9326  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9327  SCIPvarGetName(var), varfixing,
9328  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9329  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9330  isshortcut, &conflict, added) );
9331  }
9332  }
9333  assert(!conflict || !(*added));
9334 
9335  /* on conflict, fix the variable to the opposite value */
9336  if( conflict )
9337  {
9338  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9339 
9340  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9341  * with the local bound, in this case we need to store the bound change as pending bound change
9342  */
9343  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9344  {
9345  assert(tree != NULL);
9346  assert(transprob != NULL);
9347  assert(SCIPprobIsTransformed(transprob));
9348 
9349  if( varfixing )
9350  {
9351  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9352  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9353  }
9354  else
9355  {
9356  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9357  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9358  }
9359  }
9360  else
9361  {
9362  if( varfixing )
9363  {
9364  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9365  }
9366  else
9367  {
9368  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9369  }
9370  }
9371  if( nbdchgs != NULL )
9372  (*nbdchgs)++;
9373 
9374  return SCIP_OKAY;
9375  }
9376  else if( *added )
9377  {
9378  /* issue IMPLADDED event */
9379  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9380  }
9381  else
9382  {
9383  /* the implication was redundant: the inverse is also redundant */
9384  return SCIP_OKAY;
9385  }
9386 
9387  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9388 
9389  /* check, whether implied variable is binary */
9390  if( !SCIPvarIsBinary(implvar) )
9391  {
9392  SCIP_Real lb;
9393  SCIP_Real ub;
9394 
9395  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9396  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9397  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9398  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9399  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9400  * for numerical reasons, ignore variable bounds with large absolute coefficient
9401  */
9402  lb = SCIPvarGetLbGlobal(implvar);
9403  ub = SCIPvarGetUbGlobal(implvar);
9404  if( impltype == SCIP_BOUNDTYPE_UPPER )
9405  {
9406  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9407  {
9408  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9409  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9410  }
9411  }
9412  else
9413  {
9414  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9415  {
9416  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9417  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9418  }
9419  }
9420  }
9421 
9422  return SCIP_OKAY;
9423 }
9424 
9425 /** adds transitive closure for binary implication x = a -> y = b */
9426 static
9428  SCIP_VAR* var, /**< problem variable */
9429  BMS_BLKMEM* blkmem, /**< block memory */
9430  SCIP_SET* set, /**< global SCIP settings */
9431  SCIP_STAT* stat, /**< problem statistics */
9432  SCIP_PROB* transprob, /**< transformed problem */
9433  SCIP_PROB* origprob, /**< original problem */
9434  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9435  SCIP_REOPT* reopt, /**< reoptimization data structure */
9436  SCIP_LP* lp, /**< current LP data */
9437  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9438  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9439  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9440  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9441  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9442  SCIP_Bool implvarfixing, /**< fixing b in implication */
9443  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9444  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9445  )
9446 {
9447  SCIP_VAR** implvars;
9448  SCIP_BOUNDTYPE* impltypes;
9449  SCIP_Real* implbounds;
9450  int nimpls;
9451  int i;
9452 
9453  *infeasible = FALSE;
9454 
9455  /* binary variable: implications of implvar */
9456  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9457  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9458  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9459  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9460 
9461  /* if variable has too many implications, the implication graph may become too dense */
9462  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9463 
9464  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9465  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9466  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9467  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9468  * only thing that can happen is that we add the same implication twice - this does no harm
9469  */
9470  while ( i >= 0 && !(*infeasible) )
9471  {
9472  SCIP_Bool added;
9473 
9474  assert(implvars[i] != implvar);
9475 
9476  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9477  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9478  */
9479  if( SCIPvarIsActive(implvars[i]) )
9480  {
9481  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9482  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9483  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9484  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9485  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9486  }
9487  --i;
9488  }
9489 
9490  return SCIP_OKAY;
9491 }
9492 
9493 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9494  * implication to the variable's implication list;
9495  * if the implication is conflicting, the variable is fixed to the opposite value;
9496  * if the variable is already fixed to the given value, the implication is performed immediately;
9497  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9498  */
9499 static
9501  SCIP_VAR* var, /**< problem variable */
9502  BMS_BLKMEM* blkmem, /**< block memory */
9503  SCIP_SET* set, /**< global SCIP settings */
9504  SCIP_STAT* stat, /**< problem statistics */
9505  SCIP_PROB* transprob, /**< transformed problem */
9506  SCIP_PROB* origprob, /**< original problem */
9507  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9508  SCIP_REOPT* reopt, /**< reoptimization data structure */
9509  SCIP_LP* lp, /**< current LP data */
9510  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9511  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9512  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9513  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9514  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9515  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9516  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9517  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9518  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9519  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9520  )
9521 {
9522  SCIP_Bool added;
9523 
9524  assert(var != NULL);
9525  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9526  assert(SCIPvarIsActive(var));
9527  assert(implvar != NULL);
9528  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9529  assert(infeasible != NULL);
9530 
9531  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9532  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9533  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9534 
9535  if( *infeasible || var == implvar || !transitive || !added )
9536  return SCIP_OKAY;
9537 
9538  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9539 
9540  /* add transitive closure */
9541  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9542  {
9543  SCIP_Bool implvarfixing;
9544 
9545  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9546 
9547  /* binary variable: implications of implvar */
9548  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9549  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9550 
9551  /* inverse implication */
9552  if( !(*infeasible) )
9553  {
9554  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9555  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9556  }
9557  }
9558  else
9559  {
9560  /* non-binary variable: variable lower bounds of implvar */
9561  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9562  {
9563  SCIP_VAR** vlbvars;
9564  SCIP_Real* vlbcoefs;
9565  SCIP_Real* vlbconstants;
9566  int nvlbvars;
9567  int i;
9568 
9569  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9570  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9571  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9572  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9573 
9574  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9575  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9576  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9577  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9578  * is that we add the same implication twice - this does no harm
9579  */
9580  i = nvlbvars-1;
9581  while ( i >= 0 && !(*infeasible) )
9582  {
9583  assert(vlbvars[i] != implvar);
9584  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9585 
9586  /* we have x == varfixing -> y <= b and y >= c*z + d:
9587  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9588  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9589  *
9590  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9591  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9592  * aggregation variable (the one which will stay active);
9593  *
9594  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9595  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9596  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9597  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9598  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9599  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9600  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9601  * have to explicitly check that the active variable has not a variable status
9602  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9603  */
9604  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9605  {
9606  SCIP_Real vbimplbound;
9607 
9608  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9609  if( vlbcoefs[i] >= 0.0 )
9610  {
9611  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9612  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9613  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9614  infeasible, nbdchgs, &added) );
9615  }
9616  else
9617  {
9618  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9619  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9620  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9621  infeasible, nbdchgs, &added) );
9622  }
9623  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9624  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9625  }
9626  --i;
9627  }
9628  }
9629 
9630  /* non-binary variable: variable upper bounds of implvar */
9631  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9632  {
9633  SCIP_VAR** vubvars;
9634  SCIP_Real* vubcoefs;
9635  SCIP_Real* vubconstants;
9636  int nvubvars;
9637  int i;
9638 
9639  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9640  vubvars = SCIPvboundsGetVars(implvar->vubs);
9641  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9642  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9643 
9644  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9645  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9646  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9647  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9648  * is that we add the same implication twice - this does no harm
9649  */
9650  i = nvubvars-1;
9651  while ( i >= 0 && !(*infeasible) )
9652  {
9653  assert(vubvars[i] != implvar);
9654  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9655 
9656  /* we have x == varfixing -> y >= b and y <= c*z + d:
9657  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9658  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9659  *
9660  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9661  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9662  * aggregation variable (the one which will stay active);
9663  *
9664  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9665  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9666  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9667  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9668  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9669  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9670  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9671  * have to explicitly check that the active variable has not a variable status
9672  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9673  */
9674  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9675  {
9676  SCIP_Real vbimplbound;
9677 
9678  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9679  if( vubcoefs[i] >= 0.0 )
9680  {
9681  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9682  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9683  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9684  infeasible, nbdchgs, &added) );
9685  }
9686  else
9687  {
9688  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9689  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9690  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9691  infeasible, nbdchgs, &added) );
9692  }
9693  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9694  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9695  }
9696  --i;
9697  }
9698  }
9699  }
9700 
9701  return SCIP_OKAY;
9702 }
9703 
9704 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9705  * if z is binary, the corresponding valid implication for z is also added;
9706  * improves the global bounds of the variable and the vlb variable if possible
9707  */
9709  SCIP_VAR* var, /**< problem variable */
9710  BMS_BLKMEM* blkmem, /**< block memory */
9711  SCIP_SET* set, /**< global SCIP settings */
9712  SCIP_STAT* stat, /**< problem statistics */
9713  SCIP_PROB* transprob, /**< transformed problem */
9714  SCIP_PROB* origprob, /**< original problem */
9715  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9716  SCIP_REOPT* reopt, /**< reoptimization data structure */
9717  SCIP_LP* lp, /**< current LP data */
9718  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9719  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9720  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9721  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9722  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9723  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9724  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9725  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9726  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9727  )
9728 {
9729  assert(var != NULL);
9730  assert(set != NULL);
9731  assert(var->scip == set->scip);
9732  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9733  assert(infeasible != NULL);
9734 
9735  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9736 
9737  *infeasible = FALSE;
9738  if( nbdchgs != NULL )
9739  *nbdchgs = 0;
9740 
9741  switch( SCIPvarGetStatus(var) )
9742  {
9744  assert(var->data.original.transvar != NULL);
9745  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9746  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9747  break;
9748 
9749  case SCIP_VARSTATUS_COLUMN:
9750  case SCIP_VARSTATUS_LOOSE:
9751  case SCIP_VARSTATUS_FIXED:
9752  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9753  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9754  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9755 
9756  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9757  if( SCIPsetIsZero(set, vlbcoef) )
9758  {
9759  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9760  *infeasible = TRUE;
9761  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9762  {
9763  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9764  * with the local bound, in this case we need to store the bound change as pending bound change
9765  */
9766  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9767  {
9768  assert(tree != NULL);
9769  assert(transprob != NULL);
9770  assert(SCIPprobIsTransformed(transprob));
9771 
9772  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9773  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9774  }
9775  else
9776  {
9777  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9778  }
9779 
9780  if( nbdchgs != NULL )
9781  (*nbdchgs)++;
9782  }
9783  }
9784  else if( SCIPvarIsActive(vlbvar) )
9785  {
9786  SCIP_Real xlb;
9787  SCIP_Real xub;
9788  SCIP_Real zlb;
9789  SCIP_Real zub;
9790  SCIP_Real minvlb;
9791  SCIP_Real maxvlb;
9792 
9794  assert(vlbcoef != 0.0);
9795 
9796  minvlb = -SCIPsetInfinity(set);
9797  maxvlb = SCIPsetInfinity(set);
9798 
9799  xlb = SCIPvarGetLbGlobal(var);
9800  xub = SCIPvarGetUbGlobal(var);
9801  zlb = SCIPvarGetLbGlobal(vlbvar);
9802  zub = SCIPvarGetUbGlobal(vlbvar);
9803 
9804  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9805  if( vlbcoef >= 0.0 )
9806  {
9807  SCIP_Real newzub;
9808 
9809  if( !SCIPsetIsInfinity(set, xub) )
9810  {
9811  /* x >= b*z + d -> z <= (x-d)/b */
9812  newzub = (xub - vlbconstant)/vlbcoef;
9813 
9814  /* return if the new bound is less than -infinity */
9815  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9816  return SCIP_OKAY;
9817 
9818  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9819  {
9820  *infeasible = TRUE;
9821  return SCIP_OKAY;
9822  }
9823  if( SCIPsetIsFeasLT(set, newzub, zub) )
9824  {
9825  /* bound might be adjusted due to integrality condition */
9826  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9827 
9828  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9829  * with the local bound, in this case we need to store the bound change as pending bound change
9830  */
9831  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9832  {
9833  assert(tree != NULL);
9834  assert(transprob != NULL);
9835  assert(SCIPprobIsTransformed(transprob));
9836 
9837  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9838  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9839  }
9840  else
9841  {
9842  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9843  }
9844  zub = newzub;
9845 
9846  if( nbdchgs != NULL )
9847  (*nbdchgs)++;
9848  }
9849  maxvlb = vlbcoef * zub + vlbconstant;
9850  if( !SCIPsetIsInfinity(set, -zlb) )
9851  minvlb = vlbcoef * zlb + vlbconstant;
9852  }
9853  else
9854  {
9855  if( !SCIPsetIsInfinity(set, zub) )
9856  maxvlb = vlbcoef * zub + vlbconstant;
9857  if( !SCIPsetIsInfinity(set, -zlb) )
9858  minvlb = vlbcoef * zlb + vlbconstant;
9859  }
9860  }
9861  else
9862  {
9863  SCIP_Real newzlb;
9864 
9865  if( !SCIPsetIsInfinity(set, xub) )
9866  {
9867  /* x >= b*z + d -> z >= (x-d)/b */
9868  newzlb = (xub - vlbconstant)/vlbcoef;
9869 
9870  /* return if the new bound is larger than infinity */
9871  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9872  return SCIP_OKAY;
9873 
9874  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9875  {
9876  *infeasible = TRUE;
9877  return SCIP_OKAY;
9878  }
9879  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9880  {
9881  /* bound might be adjusted due to integrality condition */
9882  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9883 
9884  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9885  * with the local bound, in this case we need to store the bound change as pending bound change
9886  */
9887  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9888  {
9889  assert(tree != NULL);
9890  assert(transprob != NULL);
9891  assert(SCIPprobIsTransformed(transprob));
9892 
9893  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9894  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9895  }
9896  else
9897  {
9898  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9899  }
9900  zlb = newzlb;
9901 
9902  if( nbdchgs != NULL )
9903  (*nbdchgs)++;
9904  }
9905  maxvlb = vlbcoef * zlb + vlbconstant;
9906  if( !SCIPsetIsInfinity(set, zub) )
9907  minvlb = vlbcoef * zub + vlbconstant;
9908  }
9909  else
9910  {
9911  if( !SCIPsetIsInfinity(set, -zlb) )
9912  maxvlb = vlbcoef * zlb + vlbconstant;
9913  if( !SCIPsetIsInfinity(set, zub) )
9914  minvlb = vlbcoef * zub + vlbconstant;
9915  }
9916  }
9917  if( maxvlb < minvlb )
9918  maxvlb = minvlb;
9919 
9920  /* adjust bounds due to integrality of variable */
9921  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9922  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9923 
9924  /* check bounds for feasibility */
9925  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9926  {
9927  *infeasible = TRUE;
9928  return SCIP_OKAY;
9929  }
9930  /* improve global lower bound of variable */
9931  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9932  {
9933  /* bound might be adjusted due to integrality condition */
9934  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9935 
9936  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9937  * with the local bound, in this case we need to store the bound change as pending bound change
9938  */
9939  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9940  {
9941  assert(tree != NULL);
9942  assert(transprob != NULL);
9943  assert(SCIPprobIsTransformed(transprob));
9944 
9945  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9946  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9947  }
9948  else
9949  {
9950  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9951  }
9952  xlb = minvlb;
9953 
9954  if( nbdchgs != NULL )
9955  (*nbdchgs)++;
9956  }
9957  minvlb = xlb;
9958 
9959  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9960  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9961  {
9962  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9963  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9964  */
9965 
9966  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9967 
9968  if( vlbcoef >= 0.0 )
9969  {
9970  vlbcoef = maxvlb - minvlb;
9971  vlbconstant = minvlb;
9972  }
9973  else
9974  {
9975  vlbcoef = minvlb - maxvlb;
9976  vlbconstant = maxvlb;
9977  }
9978  }
9979 
9980  /* add variable bound to the variable bounds list */
9981  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9982  {
9983  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9984  assert(!SCIPsetIsZero(set, vlbcoef));
9985 
9986  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9987  * list, thereby also adding the variable bound (or implication) to the other variable
9988  */
9989  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9990  {
9991  /* add corresponding implication:
9992  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9993  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9994  */
9995  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9996  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9997  infeasible, nbdchgs) );
9998  }
9999  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10000  {
10001  /* add corresponding implication:
10002  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10003  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10004  */
10005  SCIP_Real implbound;
10006  implbound = -vlbconstant/vlbcoef;
10007 
10008  /* tighten the implication bound if the variable is integer */
10009  if( SCIPvarIsIntegral(vlbvar) )
10010  {
10011  if( vlbcoef >= 0 )
10012  implbound = SCIPsetFloor(set, implbound);
10013  else
10014  implbound = SCIPsetCeil(set, implbound);
10015  }
10016  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10017  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10018  implbound, transitive, infeasible, nbdchgs) );
10019  }
10020  else
10021  {
10022  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10023  }
10024  }
10025  }
10026  break;
10027 
10029  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10030  * y <= b/a * z + (d-c)/a, if a < 0
10031  */
10032  assert(var->data.aggregate.var != NULL);
10033  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10034  {
10035  /* a > 0 -> add variable lower bound */
10036  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10037  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10038  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10039  }
10040  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10041  {
10042  /* a < 0 -> add variable upper bound */
10043  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10044  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10045  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10046  }
10047  else
10048  {
10049  SCIPerrorMessage("scalar is zero in aggregation\n");
10050  return SCIP_INVALIDDATA;
10051  }
10052  break;
10053 
10055  /* nothing to do here */
10056  break;
10057 
10059  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10060  assert(var->negatedvar != NULL);
10062  assert(var->negatedvar->negatedvar == var);
10063  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10064  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10065  nbdchgs) );
10066  break;
10067 
10068  default:
10069  SCIPerrorMessage("unknown variable status\n");
10070  return SCIP_INVALIDDATA;
10071  }
10072 
10073  return SCIP_OKAY;
10074 }
10075 
10076 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10077  * if z is binary, the corresponding valid implication for z is also added;
10078  * updates the global bounds of the variable and the vub variable correspondingly
10079  */
10081  SCIP_VAR* var, /**< problem variable */
10082  BMS_BLKMEM* blkmem, /**< block memory */
10083  SCIP_SET* set, /**< global SCIP settings */
10084  SCIP_STAT* stat, /**< problem statistics */
10085  SCIP_PROB* transprob, /**< transformed problem */
10086  SCIP_PROB* origprob, /**< original problem */
10087  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10088  SCIP_REOPT* reopt, /**< reoptimization data structure */
10089  SCIP_LP* lp, /**< current LP data */
10090  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10091  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10092  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10093  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10094  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10095  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10096  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10097  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10098  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10099  )
10100 {
10101  assert(var != NULL);
10102  assert(set != NULL);
10103  assert(var->scip == set->scip);
10104  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10105  assert(infeasible != NULL);
10106 
10107  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10108 
10109  *infeasible = FALSE;
10110  if( nbdchgs != NULL )
10111  *nbdchgs = 0;
10112 
10113  switch( SCIPvarGetStatus(var) )
10114  {
10116  assert(var->data.original.transvar != NULL);
10117  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10118  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10119  break;
10120 
10121  case SCIP_VARSTATUS_COLUMN:
10122  case SCIP_VARSTATUS_LOOSE:
10123  case SCIP_VARSTATUS_FIXED:
10124  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10125  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10126  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10127  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10128 
10129  /* if the vub coefficient is zero, just update the upper bound of the variable */
10130  if( SCIPsetIsZero(set, vubcoef) )
10131  {
10132  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10133  *infeasible = TRUE;
10134  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10135  {
10136  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10137  * with the local bound, in this case we need to store the bound change as pending bound change
10138  */
10139  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10140  {
10141  assert(tree != NULL);
10142  assert(transprob != NULL);
10143  assert(SCIPprobIsTransformed(transprob));
10144 
10145  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10146  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10147  }
10148  else
10149  {
10150  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10151  }
10152 
10153  if( nbdchgs != NULL )
10154  (*nbdchgs)++;
10155  }
10156  }
10157  else if( SCIPvarIsActive(vubvar) )
10158  {
10159  SCIP_Real xlb;
10160  SCIP_Real xub;
10161  SCIP_Real zlb;
10162  SCIP_Real zub;
10163  SCIP_Real minvub;
10164  SCIP_Real maxvub;
10165 
10167  assert(vubcoef != 0.0);
10168 
10169  minvub = -SCIPsetInfinity(set);
10170  maxvub = SCIPsetInfinity(set);
10171 
10172  xlb = SCIPvarGetLbGlobal(var);
10173  xub = SCIPvarGetUbGlobal(var);
10174  zlb = SCIPvarGetLbGlobal(vubvar);
10175  zub = SCIPvarGetUbGlobal(vubvar);
10176 
10177  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10178  if( vubcoef >= 0.0 )
10179  {
10180  SCIP_Real newzlb;
10181 
10182  if( !SCIPsetIsInfinity(set, -xlb) )
10183  {
10184  /* x <= b*z + d -> z >= (x-d)/b */
10185  newzlb = (xlb - vubconstant)/vubcoef;
10186  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10187  {
10188  *infeasible = TRUE;
10189  return SCIP_OKAY;
10190  }
10191  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10192  {
10193  /* bound might be adjusted due to integrality condition */
10194  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10195 
10196  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10197  * with the local bound, in this case we need to store the bound change as pending bound change
10198  */
10199  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10200  {
10201  assert(tree != NULL);
10202  assert(transprob != NULL);
10203  assert(SCIPprobIsTransformed(transprob));
10204 
10205  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10206  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10207  }
10208  else
10209  {
10210  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10211  }
10212  zlb = newzlb;
10213 
10214  if( nbdchgs != NULL )
10215  (*nbdchgs)++;
10216  }
10217  minvub = vubcoef * zlb + vubconstant;
10218  if( !SCIPsetIsInfinity(set, zub) )
10219  maxvub = vubcoef * zub + vubconstant;
10220  }
10221  else
10222  {
10223  if( !SCIPsetIsInfinity(set, zub) )
10224  maxvub = vubcoef * zub + vubconstant;
10225  if( !SCIPsetIsInfinity(set, -zlb) )
10226  minvub = vubcoef * zlb + vubconstant;
10227  }
10228  }
10229  else
10230  {
10231  SCIP_Real newzub;
10232 
10233  if( !SCIPsetIsInfinity(set, -xlb) )
10234  {
10235  /* x <= b*z + d -> z <= (x-d)/b */
10236  newzub = (xlb - vubconstant)/vubcoef;
10237  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10238  {
10239  *infeasible = TRUE;
10240  return SCIP_OKAY;
10241  }
10242  if( SCIPsetIsFeasLT(set, newzub, zub) )
10243  {
10244  /* bound might be adjusted due to integrality condition */
10245  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10246 
10247  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10248  * with the local bound, in this case we need to store the bound change as pending bound change
10249  */
10250  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10251  {
10252  assert(tree != NULL);
10253  assert(transprob != NULL);
10254  assert(SCIPprobIsTransformed(transprob));
10255 
10256  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10257  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10258  }
10259  else
10260  {
10261  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10262  }
10263  zub = newzub;
10264 
10265  if( nbdchgs != NULL )
10266  (*nbdchgs)++;
10267  }
10268  minvub = vubcoef * zub + vubconstant;
10269  if( !SCIPsetIsInfinity(set, -zlb) )
10270  maxvub = vubcoef * zlb + vubconstant;
10271  }
10272  else
10273  {
10274  if( !SCIPsetIsInfinity(set, zub) )
10275  minvub = vubcoef * zub + vubconstant;
10276  if( !SCIPsetIsInfinity(set, -zlb) )
10277  maxvub = vubcoef * zlb + vubconstant;
10278  }
10279  }
10280  if( minvub > maxvub )
10281  minvub = maxvub;
10282 
10283  /* adjust bounds due to integrality of vub variable */
10284  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10285  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10286 
10287  /* check bounds for feasibility */
10288  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10289  {
10290  *infeasible = TRUE;
10291  return SCIP_OKAY;
10292  }
10293 
10294  /* improve global upper bound of variable */
10295  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10296  {
10297  /* bound might be adjusted due to integrality condition */
10298  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10299 
10300  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10301  * with the local bound, in this case we need to store the bound change as pending bound change
10302  */
10303  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10304  {
10305  assert(tree != NULL);
10306  assert(transprob != NULL);
10307  assert(SCIPprobIsTransformed(transprob));
10308 
10309  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10310  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10311  }
10312  else
10313  {
10314  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10315  }
10316  xub = maxvub;
10317 
10318  if( nbdchgs != NULL )
10319  (*nbdchgs)++;
10320  }
10321  maxvub = xub;
10322 
10323  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10324  if( SCIPvarIsBinary(vubvar) )
10325  {
10326  /* b > 0: x <= (maxvub - minvub) * z + minvub
10327  * b < 0: x <= (minvub - maxvub) * z + maxvub
10328  */
10329 
10330  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10331 
10332  if( vubcoef >= 0.0 )
10333  {
10334  vubcoef = maxvub - minvub;
10335  vubconstant = minvub;
10336  }
10337  else
10338  {
10339  vubcoef = minvub - maxvub;
10340  vubconstant = maxvub;
10341  }
10342  }
10343 
10344  /* add variable bound to the variable bounds list */
10345  if( SCIPsetIsFeasLT(set, minvub, xub) )
10346  {
10347  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10348  assert(!SCIPsetIsZero(set, vubcoef));
10349 
10350  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10351  * list, thereby also adding the variable bound (or implication) to the other variable
10352  */
10353  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10354  {
10355  /* add corresponding implication:
10356  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10357  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10358  */
10359  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10360  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10361  infeasible, nbdchgs) );
10362  }
10363  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10364  {
10365  /* add corresponding implication:
10366  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10367  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10368  */
10369  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10370  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10371  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10372  }
10373  else
10374  {
10375  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10376  }
10377  }
10378  }
10379  break;
10380 
10382  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10383  * y >= b/a * z + (d-c)/a, if a < 0
10384  */
10385  assert(var->data.aggregate.var != NULL);
10386  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10387  {
10388  /* a > 0 -> add variable upper bound */
10389  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10390  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10391  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10392  }
10393  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10394  {
10395  /* a < 0 -> add variable lower bound */
10396  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10397  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10398  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10399  }
10400  else
10401  {
10402  SCIPerrorMessage("scalar is zero in aggregation\n");
10403  return SCIP_INVALIDDATA;
10404  }
10405  break;
10406 
10408  /* nothing to do here */
10409  break;
10410 
10412  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10413  assert(var->negatedvar != NULL);
10415  assert(var->negatedvar->negatedvar == var);
10416  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10417  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10418  nbdchgs) );
10419  break;
10420 
10421  default:
10422  SCIPerrorMessage("unknown variable status\n");
10423  return SCIP_INVALIDDATA;
10424  }
10425 
10426  return SCIP_OKAY;
10427 }
10428 
10429 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10430  * also adds the corresponding implication or variable bound to the implied variable;
10431  * if the implication is conflicting, the variable is fixed to the opposite value;
10432  * if the variable is already fixed to the given value, the implication is performed immediately;
10433  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10434  */
10436  SCIP_VAR* var, /**< problem variable */
10437  BMS_BLKMEM* blkmem, /**< block memory */
10438  SCIP_SET* set, /**< global SCIP settings */
10439  SCIP_STAT* stat, /**< problem statistics */
10440  SCIP_PROB* transprob, /**< transformed problem */
10441  SCIP_PROB* origprob, /**< original problem */
10442  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10443  SCIP_REOPT* reopt, /**< reoptimization data structure */
10444  SCIP_LP* lp, /**< current LP data */
10445  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10446  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10447  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10448  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10449  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10450  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10451  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10452  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10453  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10454  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10455  )
10456 {
10457  assert(var != NULL);
10458  assert(set != NULL);
10459  assert(var->scip == set->scip);
10460  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10461  assert(infeasible != NULL);
10462 
10463  *infeasible = FALSE;
10464  if( nbdchgs != NULL )
10465  *nbdchgs = 0;
10466 
10467  switch( SCIPvarGetStatus(var) )
10468  {
10470  assert(var->data.original.transvar != NULL);
10471  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10472  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10473  nbdchgs) );
10474  break;
10475 
10476  case SCIP_VARSTATUS_COLUMN:
10477  case SCIP_VARSTATUS_LOOSE:
10478  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10479  * the variable, the implication can be applied directly;
10480  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10481  */
10482  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10483  {
10484  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10485  {
10486  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10487  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10488  }
10489  }
10490  else
10491  {
10492  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10493  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10494  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10495  {
10496  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10497  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10498  }
10499  }
10500  break;
10501 
10502  case SCIP_VARSTATUS_FIXED:
10503  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10504  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10505  {
10506  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10507  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10508  }
10509  break;
10510 
10512  /* implication added for x == 1:
10513  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10514  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10515  * implication added for x == 0:
10516  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10517  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10518  *
10519  * use only binary variables z
10520  */
10521  assert(var->data.aggregate.var != NULL);
10522  if( SCIPvarIsBinary(var->data.aggregate.var) )
10523  {
10524  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10525  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10526 
10527  if( var->data.aggregate.scalar > 0 )
10528  {
10529  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10530  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10531  nbdchgs) );
10532  }
10533  else
10534  {
10535  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10536  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10537  nbdchgs) );
10538  }
10539  }
10540  break;
10541 
10543  /* nothing to do here */
10544  break;
10545 
10547  /* implication added for x == 1:
10548  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10549  * implication added for x == 0:
10550  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10551  */
10552  assert(var->negatedvar != NULL);
10554  assert(var->negatedvar->negatedvar == var);
10555  assert(SCIPvarIsBinary(var->negatedvar));
10556 
10558  {
10559  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10560  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10561  }
10562  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10563  else
10564  {
10565  /* if the implied variable is of binary type exchange the variables */
10566  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10567  {
10568  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10569  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10570  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10571  infeasible, nbdchgs) );
10572  }
10573  else
10574  {
10575  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10576  * implication as variable bounds
10577  */
10578 
10579  /* add variable lower bound on the negation of var */
10580  if( varfixing )
10581  {
10582  /* (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
10583  * as variable lower bound
10584  */
10585  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10586  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10587  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10588  }
10589  else
10590  {
10591  /* (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
10592  * as variable upper bound
10593  */
10594  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10595  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10596  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10597  }
10598 
10599  /* add variable bound on implvar */
10600  if( impltype == SCIP_BOUNDTYPE_UPPER )
10601  {
10602  /* (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
10603  * as variable upper bound
10604  */
10605  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10606  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10607  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10608  }
10609  else
10610  {
10611  /* (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
10612  * as variable upper bound
10613  */
10614  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10615  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10616  transitive, infeasible, nbdchgs) );
10617  }
10618  }
10619  }
10620  break;
10621 
10622  default:
10623  SCIPerrorMessage("unknown variable status\n");
10624  return SCIP_INVALIDDATA;
10625  }
10626 
10627  return SCIP_OKAY;
10628 }
10629 
10630 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10631  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10632  * both variables must be active, variable x must be binary
10633  */
10635  SCIP_VAR* var, /**< problem variable x */
10636  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10637  SCIP_VAR* implvar, /**< variable y to search for */
10638  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10639  )
10640 {
10641  assert(var != NULL);
10642  assert(implvar != NULL);
10643  assert(SCIPvarIsActive(var));
10644  assert(SCIPvarIsActive(implvar));
10645  assert(SCIPvarIsBinary(var));
10646 
10647  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10648 }
10649 
10650 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10651  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10652  * both variables must be active binary variables
10653  */
10655  SCIP_VAR* var, /**< problem variable x */
10656  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10657  SCIP_VAR* implvar, /**< variable y to search for */
10658  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10659  )
10660 {
10661  assert(SCIPvarIsBinary(implvar));
10662 
10663  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10664 }
10665 
10666 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10668  SCIP_VAR* var, /**< problem variable */
10669  BMS_BLKMEM* blkmem, /**< block memory */
10670  SCIP_SET* set, /**< global SCIP settings */
10671  SCIP_STAT* stat, /**< problem statistics */
10672  SCIP_PROB* transprob, /**< transformed problem */
10673  SCIP_PROB* origprob, /**< original problem */
10674  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10675  SCIP_REOPT* reopt, /**< reoptimization data structure */
10676  SCIP_LP* lp, /**< current LP data */
10677  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10678  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10679  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10680  SCIP_Bool value, /**< value to fix variable to */
10681  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10682  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10683  )
10684 {
10685  assert(var != NULL);
10686  assert(set != NULL);
10687  assert(var->scip == set->scip);
10688  assert(infeasible != NULL);
10689 
10690  *infeasible = FALSE;
10691 
10692  if( value == FALSE )
10693  {
10694  if( var->glbdom.lb > 0.5 )
10695  *infeasible = TRUE;
10696  else if( var->glbdom.ub > 0.5 )
10697  {
10698  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10699  * with the local bound, in this case we need to store the bound change as pending bound change
10700  */
10701  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10702  {
10703  assert(tree != NULL);
10704  assert(transprob != NULL);
10705  assert(SCIPprobIsTransformed(transprob));
10706 
10707  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10708  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10709  }
10710  else
10711  {
10712  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10713  }
10714 
10715  if( nbdchgs != NULL )
10716  (*nbdchgs)++;
10717  }
10718  }
10719  else
10720  {
10721  if( var->glbdom.ub < 0.5 )
10722  *infeasible = TRUE;
10723  else if( var->glbdom.lb < 0.5 )
10724  {
10725  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10726  * with the local bound, in this case we need to store the bound change as pending bound change
10727  */
10728  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10729  {
10730  assert(tree != NULL);
10731  assert(transprob != NULL);
10732  assert(SCIPprobIsTransformed(transprob));
10733 
10734  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10735  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10736  }
10737  else
10738  {
10739  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10740  }
10741 
10742  if( nbdchgs != NULL )
10743  (*nbdchgs)++;
10744  }
10745  }
10746 
10747  /* during presolving, the variable should have been removed immediately from all its cliques */
10748  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10749 
10750  return SCIP_OKAY;
10751 }
10752 
10753 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10754  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10755  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10756  * the opposite of the value they take in the clique
10757  */
10759  SCIP_VAR* var, /**< problem variable */
10760  BMS_BLKMEM* blkmem, /**< block memory */
10761  SCIP_SET* set, /**< global SCIP settings */
10762  SCIP_STAT* stat, /**< problem statistics */
10763  SCIP_PROB* transprob, /**< transformed problem */
10764  SCIP_PROB* origprob, /**< original problem */
10765  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10766  SCIP_REOPT* reopt, /**< reoptimization data structure */
10767  SCIP_LP* lp, /**< current LP data */
10768  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10769  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10770  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10771  SCIP_Bool value, /**< value of the variable in the clique */
10772  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10773  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10774  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10775  )
10776 {
10777  assert(var != NULL);
10778  assert(set != NULL);
10779  assert(var->scip == set->scip);
10780  assert(SCIPvarIsBinary(var));
10781  assert(infeasible != NULL);
10782 
10783  *infeasible = FALSE;
10784 
10785  /* get corresponding active problem variable */
10786  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10791  assert(SCIPvarIsBinary(var));
10792 
10793  /* only column and loose variables may be member of a clique */
10795  {
10796  SCIP_Bool doubleentry;
10797  SCIP_Bool oppositeentry;
10798 
10799  /* add variable to clique */
10800  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10801 
10802  /* add clique to variable's clique list */
10803  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10804 
10805  /* check consistency of cliquelist */
10806  SCIPcliquelistCheck(var->cliquelist, var);
10807 
10808  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10809  if( doubleentry )
10810  {
10811  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10812  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10813  }
10814 
10815  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10816  * to the opposite of the value they take in the clique
10817  */
10818  if( oppositeentry )
10819  {
10820  SCIP_VAR** vars;
10821  SCIP_Bool* values;
10822  int nvars;
10823  int i;
10824 
10825  nvars = SCIPcliqueGetNVars(clique);
10826  vars = SCIPcliqueGetVars(clique);
10827  values = SCIPcliqueGetValues(clique);
10828  for( i = 0; i < nvars && !(*infeasible); ++i )
10829  {
10830  if( vars[i] == var )
10831  continue;
10832 
10833  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10834  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10835  }
10836  }
10837  }
10838 
10839  return SCIP_OKAY;
10840 }
10841 
10842 /** adds a filled clique to the cliquelists of all corresponding variables */
10844  SCIP_VAR** vars, /**< problem variables */
10845  SCIP_Bool* values, /**< values of the variables in the clique */
10846  int nvars, /**< number of problem variables */
10847  BMS_BLKMEM* blkmem, /**< block memory */
10848  SCIP_SET* set, /**< global SCIP settings */
10849  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10850  )
10851 {
10852  SCIP_VAR* var;
10853  int v;
10854 
10855  assert(vars != NULL);
10856  assert(values != NULL);
10857  assert(nvars > 0);
10858  assert(set != NULL);
10859  assert(blkmem != NULL);
10860  assert(clique != NULL);
10861 
10862  for( v = nvars - 1; v >= 0; --v )
10863  {
10864  var = vars[v];
10865  assert(SCIPvarIsBinary(var));
10867 
10868  /* add clique to variable's clique list */
10869  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10870 
10871  /* check consistency of cliquelist */
10872  SCIPcliquelistCheck(var->cliquelist, var);
10873  }
10874 
10875  return SCIP_OKAY;
10876 }
10877 
10878 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10879  * itself
10880  */
10882  SCIP_VAR* var, /**< problem variable */
10883  BMS_BLKMEM* blkmem, /**< block memory */
10884  SCIP_SET* set, /**< global SCIP settings */
10885  SCIP_Bool value, /**< value of the variable in the clique */
10886  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10887  )
10888 {
10889  assert(var != NULL);
10890  assert(SCIPvarIsBinary(var));
10892 
10893  /* add clique to variable's clique list */
10894  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10895 
10896  return SCIP_OKAY;
10897 }
10898 
10899 
10900 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10901  * itself
10902  */
10904  SCIP_VAR* var, /**< problem variable */
10905  BMS_BLKMEM* blkmem, /**< block memory */
10906  SCIP_Bool value, /**< value of the variable in the clique */
10907  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10908  )
10909 {
10910  assert(var != NULL);
10911  assert(SCIPvarIsBinary(var));
10912 
10913  /* delete clique from variable's clique list */
10914  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10915 
10916  return SCIP_OKAY;
10917 }
10918 
10919 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10921  SCIP_VAR* var, /**< problem variable */
10922  BMS_BLKMEM* blkmem, /**< block memory */
10923  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10924  SCIP_Bool value, /**< value of the variable in the clique */
10925  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10926  )
10927 {
10928  assert(var != NULL);
10929  assert(SCIPvarIsBinary(var));
10930 
10931  /* get corresponding active problem variable */
10932  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10937  assert(SCIPvarIsBinary(var));
10938 
10939  /* only column and loose variables may be member of a clique */
10941  {
10942  /* delete clique from variable's clique list */
10943  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10944 
10945  /* delete variable from clique */
10946  SCIPcliqueDelVar(clique, cliquetable, var, value);
10947 
10948  /* check consistency of cliquelist */
10949  SCIPcliquelistCheck(var->cliquelist, var);
10950  }
10951 
10952  return SCIP_OKAY;
10953 }
10954 
10955 /** returns whether there is a clique that contains both given variable/value pairs;
10956  * the variables must be active binary variables;
10957  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10958  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10959  *
10960  * @note a variable with it's negated variable are NOT! in a clique
10961  * @note a variable with itself are in a clique
10962  */
10964  SCIP_VAR* var1, /**< first variable */
10965  SCIP_Bool value1, /**< value of first variable */
10966  SCIP_VAR* var2, /**< second variable */
10967  SCIP_Bool value2, /**< value of second variable */
10968  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10969  )
10970 {
10971  assert(var1 != NULL);
10972  assert(var2 != NULL);
10973  assert(SCIPvarIsActive(var1));
10974  assert(SCIPvarIsActive(var2));
10975  assert(SCIPvarIsBinary(var1));
10976  assert(SCIPvarIsBinary(var2));
10977 
10978  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10979  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10980 }
10981 
10982 /** actually changes the branch factor of the variable and of all parent variables */
10983 static
10985  SCIP_VAR* var, /**< problem variable */
10986  SCIP_SET* set, /**< global SCIP settings */
10987  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10988  )
10989 {
10990  SCIP_VAR* parentvar;
10991  SCIP_Real eps;
10992  int i;
10993 
10994  assert(var != NULL);
10995  assert(set != NULL);
10996  assert(var->scip == set->scip);
10997 
10998  /* only use positive values */
10999  eps = SCIPsetEpsilon(set);
11000  branchfactor = MAX(branchfactor, eps);
11001 
11002  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11003 
11004  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11005  return SCIP_OKAY;
11006 
11007  /* change the branch factor */
11008  var->branchfactor = branchfactor;
11009 
11010  /* process parent variables */
11011  for( i = 0; i < var->nparentvars; ++i )
11012  {
11013  parentvar = var->parentvars[i];
11014  assert(parentvar != NULL);
11015 
11016  switch( SCIPvarGetStatus(parentvar) )
11017  {
11019  /* do not change priorities across the border between transformed and original problem */
11020  break;
11021 
11022  case SCIP_VARSTATUS_COLUMN:
11023  case SCIP_VARSTATUS_LOOSE:
11024  case SCIP_VARSTATUS_FIXED:
11026  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11027  SCIPABORT();
11028  return SCIP_INVALIDDATA; /*lint !e527*/
11029 
11032  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11033  break;
11034 
11035  default:
11036  SCIPerrorMessage("unknown variable status\n");
11037  SCIPABORT();
11038  return SCIP_ERROR; /*lint !e527*/
11039  }
11040  }
11041 
11042  return SCIP_OKAY;
11043 }
11044 
11045 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11046  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11047  */
11049  SCIP_VAR* var, /**< problem variable */
11050  SCIP_SET* set, /**< global SCIP settings */
11051  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11052  )
11053 {
11054  int v;
11055 
11056  assert(var != NULL);
11057  assert(set != NULL);
11058  assert(var->scip == set->scip);
11059  assert(branchfactor >= 0.0);
11060 
11061  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11062 
11063  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11064  return SCIP_OKAY;
11065 
11066  /* change priorities of attached variables */
11067  switch( SCIPvarGetStatus(var) )
11068  {
11070  if( var->data.original.transvar != NULL )
11071  {
11072  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11073  }
11074  else
11075  {
11076  assert(set->stage == SCIP_STAGE_PROBLEM);
11077  var->branchfactor = branchfactor;
11078  }
11079  break;
11080 
11081  case SCIP_VARSTATUS_COLUMN:
11082  case SCIP_VARSTATUS_LOOSE:
11083  case SCIP_VARSTATUS_FIXED:
11084  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11085  break;
11086 
11088  assert(var->data.aggregate.var != NULL);
11089  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11090  break;
11091 
11093  assert(!var->donotmultaggr);
11094  for( v = 0; v < var->data.multaggr.nvars; ++v )
11095  {
11096  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11097  }
11098  break;
11099 
11101  assert(var->negatedvar != NULL);
11103  assert(var->negatedvar->negatedvar == var);
11104  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11105  break;
11106 
11107  default:
11108  SCIPerrorMessage("unknown variable status\n");
11109  SCIPABORT();
11110  return SCIP_ERROR; /*lint !e527*/
11111  }
11112 
11113  return SCIP_OKAY;
11114 }
11115 
11116 /** actually changes the branch priority of the variable and of all parent variables */
11117 static
11119  SCIP_VAR* var, /**< problem variable */
11120  int branchpriority /**< branching priority of the variable */
11121  )
11122 {
11123  SCIP_VAR* parentvar;
11124  int i;
11125 
11126  assert(var != NULL);
11127 
11128  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11129  var->name, var->branchpriority, branchpriority);
11130 
11131  if( branchpriority == var->branchpriority )
11132  return SCIP_OKAY;
11133 
11134  /* change the branch priority */
11135  var->branchpriority = branchpriority;
11136 
11137  /* process parent variables */
11138  for( i = 0; i < var->nparentvars; ++i )
11139  {
11140  parentvar = var->parentvars[i];
11141  assert(parentvar != NULL);
11142 
11143  switch( SCIPvarGetStatus(parentvar) )
11144  {
11146  /* do not change priorities across the border between transformed and original problem */
11147  break;
11148 
11149  case SCIP_VARSTATUS_COLUMN:
11150  case SCIP_VARSTATUS_LOOSE:
11151  case SCIP_VARSTATUS_FIXED:
11153  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11154  SCIPABORT();
11155  return SCIP_INVALIDDATA; /*lint !e527*/
11156 
11159  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11160  break;
11161 
11162  default:
11163  SCIPerrorMessage("unknown variable status\n");
11164  return SCIP_ERROR;
11165  }
11166  }
11167 
11168  return SCIP_OKAY;
11169 }
11170 
11171 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11172  * with lower priority in selection of branching variable
11173  */
11175  SCIP_VAR* var, /**< problem variable */
11176  int branchpriority /**< branching priority of the variable */
11177  )
11178 {
11179  int v;
11180 
11181  assert(var != NULL);
11182 
11183  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11184 
11185  if( var->branchpriority == branchpriority )
11186  return SCIP_OKAY;
11187 
11188  /* change priorities of attached variables */
11189  switch( SCIPvarGetStatus(var) )
11190  {
11192  if( var->data.original.transvar != NULL )
11193  {
11194  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11195  }
11196  else
11197  var->branchpriority = branchpriority;
11198  break;
11199 
11200  case SCIP_VARSTATUS_COLUMN:
11201  case SCIP_VARSTATUS_LOOSE:
11202  case SCIP_VARSTATUS_FIXED:
11203  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11204  break;
11205 
11207  assert(var->data.aggregate.var != NULL);
11208  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11209  break;
11210 
11212  assert(!var->donotmultaggr);
11213  for( v = 0; v < var->data.multaggr.nvars; ++v )
11214  {
11215  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11216  }
11217  break;
11218 
11220  assert(var->negatedvar != NULL);
11222  assert(var->negatedvar->negatedvar == var);
11223  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11224  break;
11225 
11226  default:
11227  SCIPerrorMessage("unknown variable status\n");
11228  SCIPABORT();
11229  return SCIP_ERROR; /*lint !e527*/
11230  }
11231 
11232  return SCIP_OKAY;
11233 }
11234 
11235 /** actually changes the branch direction of the variable and of all parent variables */
11236 static
11238  SCIP_VAR* var, /**< problem variable */
11239  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11240  )
11241 {
11242  SCIP_VAR* parentvar;
11243  int i;
11244 
11245  assert(var != NULL);
11246 
11247  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11248  var->name, var->branchdirection, branchdirection);
11249 
11250  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11251  return SCIP_OKAY;
11252 
11253  /* change the branch direction */
11254  var->branchdirection = branchdirection; /*lint !e641*/
11255 
11256  /* process parent variables */
11257  for( i = 0; i < var->nparentvars; ++i )
11258  {
11259  parentvar = var->parentvars[i];
11260  assert(parentvar != NULL);
11261 
11262  switch( SCIPvarGetStatus(parentvar) )
11263  {
11265  /* do not change directions across the border between transformed and original problem */
11266  break;
11267 
11268  case SCIP_VARSTATUS_COLUMN:
11269  case SCIP_VARSTATUS_LOOSE:
11270  case SCIP_VARSTATUS_FIXED:
11272  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11273  SCIPABORT();
11274  return SCIP_INVALIDDATA; /*lint !e527*/
11275 
11277  if( parentvar->data.aggregate.scalar > 0.0 )
11278  {
11279  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11280  }
11281  else
11282  {
11283  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11284  }
11285  break;
11286 
11288  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11289  break;
11290 
11291  default:
11292  SCIPerrorMessage("unknown variable status\n");
11293  SCIPABORT();
11294  return SCIP_ERROR; /*lint !e527*/
11295  }
11296  }
11297 
11298  return SCIP_OKAY;
11299 }
11300 
11301 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11302  * with lower direction in selection of branching variable
11303  */
11305  SCIP_VAR* var, /**< problem variable */
11306  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11307  )
11308 {
11309  int v;
11310 
11311  assert(var != NULL);
11312 
11313  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11314 
11315  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11316  return SCIP_OKAY;
11317 
11318  /* change directions of attached variables */
11319  switch( SCIPvarGetStatus(var) )
11320  {
11322  if( var->data.original.transvar != NULL )
11323  {
11324  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11325  }
11326  else
11327  var->branchdirection = branchdirection; /*lint !e641*/
11328  break;
11329 
11330  case SCIP_VARSTATUS_COLUMN:
11331  case SCIP_VARSTATUS_LOOSE:
11332  case SCIP_VARSTATUS_FIXED:
11333  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11334  break;
11335 
11337  assert(var->data.aggregate.var != NULL);
11338  if( var->data.aggregate.scalar > 0.0 )
11339  {
11340  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11341  }
11342  else
11343  {
11345  }
11346  break;
11347 
11349  assert(!var->donotmultaggr);
11350  for( v = 0; v < var->data.multaggr.nvars; ++v )
11351  {
11352  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11353  assert(var->data.multaggr.vars[v] != NULL);
11355  {
11356  if( var->data.multaggr.scalars[v] > 0.0 )
11357  {
11358  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11359  }
11360  else
11361  {
11363  }
11364  }
11365  }
11366  break;
11367 
11369  assert(var->negatedvar != NULL);
11371  assert(var->negatedvar->negatedvar == var);
11373  break;
11374 
11375  default:
11376  SCIPerrorMessage("unknown variable status\n");
11377  SCIPABORT();
11378  return SCIP_ERROR; /*lint !e527*/
11379  }
11380 
11381  return SCIP_OKAY;
11382 }
11383 
11384 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11385  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11386  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11387  * are equal, which means both variables are equal
11388  */
11390  SCIP_VAR* var1, /**< first problem variable */
11391  SCIP_VAR* var2 /**< second problem variable */
11392  )
11393 {
11394  assert(var1 != NULL);
11395  assert(var2 != NULL);
11398 
11400  var1 = SCIPvarGetNegatedVar(var1);
11402  var2 = SCIPvarGetNegatedVar(var2);
11403 
11404  assert(var1 != NULL);
11405  assert(var2 != NULL);
11406 
11407  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11408  return -1;
11409  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11410  return +1;
11411 
11412  assert(var1 == var2);
11413  return 0;
11414 }
11415 
11416 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11417  * variables are handled as the same variables
11418  */
11419 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11421  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11422 }
11423 
11424 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11425  * variable index; returns 0 if both indices are equal, which means both variables are equal
11426  */
11427 int SCIPvarCompare(
11428  SCIP_VAR* var1, /**< first problem variable */
11429  SCIP_VAR* var2 /**< second problem variable */
11430  )
11431 {
11432  assert(var1 != NULL);
11433  assert(var2 != NULL);
11434 
11435  if( var1->index < var2->index )
11436  return -1;
11437  else if( var1->index > var2->index )
11438  return +1;
11439  else
11440  {
11441  assert(var1 == var2);
11442  return 0;
11443  }
11444 }
11445 
11446 /** comparison method for sorting variables by non-decreasing index */
11447 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11449  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11450 }
11451 
11452 /** comparison method for sorting variables by non-decreasing objective coefficient */
11453 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11455  SCIP_Real obj1;
11456  SCIP_Real obj2;
11457 
11458  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11459  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11460 
11461  if( obj1 < obj2 )
11462  return -1;
11463  else if( obj1 > obj2 )
11464  return +1;
11465  else
11466  return 0;
11467 }
11468 
11469 /** hash key retrieval function for variables */
11470 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11471 { /*lint --e{715}*/
11472  return elem;
11473 }
11474 
11475 /** returns TRUE iff the indices of both variables are equal */
11476 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11477 { /*lint --e{715}*/
11478  if( key1 == key2 )
11479  return TRUE;
11480  return FALSE;
11481 }
11482 
11483 /** returns the hash value of the key */
11484 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11485 { /*lint --e{715}*/
11486  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11487  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11488 }
11489 
11490 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11492  SCIP_SET* set, /**< global SCIP settings */
11493  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11494  * variables, if enough slots exist
11495  */
11496  int* nvars, /**< number of given variables, and as output number of active variables,
11497  * if enough slots exist
11498  */
11499  int varssize, /**< available slots in vars array */
11500  int* requiredsize /**< pointer to store the required array size for the active variables */
11501  )
11502 {
11503  SCIP_VAR** activevars;
11504  int nactivevars;
11505  int activevarssize;
11506 
11507  SCIP_VAR* var;
11508  int v;
11509 
11510  SCIP_VAR** tmpvars;
11511  SCIP_VAR** multvars;
11512  int tmpvarssize;
11513  int ntmpvars;
11514  int noldtmpvars;
11515  int nmultvars;
11516 
11517  assert(set != NULL);
11518  assert(nvars != NULL);
11519  assert(vars != NULL || *nvars == 0);
11520  assert(varssize >= *nvars);
11521  assert(requiredsize != NULL);
11522 
11523  *requiredsize = 0;
11524 
11525  if( *nvars == 0 )
11526  return SCIP_OKAY;
11527 
11528  nactivevars = 0;
11529  activevarssize = *nvars;
11530  ntmpvars = *nvars;
11531  tmpvarssize = *nvars;
11532 
11533  /* temporary memory */
11534  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11535  /* coverity[copy_paste_error] */
11536  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11537 
11538  noldtmpvars = ntmpvars;
11539 
11540  /* sort all variables to combine equal variables easily */
11541  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11542  for( v = ntmpvars - 1; v > 0; --v )
11543  {
11544  /* combine same variables */
11545  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11546  {
11547  --ntmpvars;
11548  tmpvars[v] = tmpvars[ntmpvars];
11549  }
11550  }
11551  /* sort all variables again to combine equal variables later on */
11552  if( noldtmpvars > ntmpvars )
11553  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11554 
11555  /* collect for each variable the representation in active variables */
11556  while( ntmpvars >= 1 )
11557  {
11558  --ntmpvars;
11559  var = tmpvars[ntmpvars];
11560  assert( var != NULL );
11561 
11562  switch( SCIPvarGetStatus(var) )
11563  {
11565  if( var->data.original.transvar == NULL )
11566  {
11567  SCIPerrorMessage("original variable has no transformed variable attached\n");
11568  SCIPABORT();
11569  return SCIP_INVALIDDATA; /*lint !e527*/
11570  }
11571  tmpvars[ntmpvars] = var->data.original.transvar;
11572  ++ntmpvars;
11573  break;
11574 
11576  tmpvars[ntmpvars] = var->data.aggregate.var;
11577  ++ntmpvars;
11578  break;
11579 
11581  tmpvars[ntmpvars] = var->negatedvar;
11582  ++ntmpvars;
11583  break;
11584 
11585  case SCIP_VARSTATUS_LOOSE:
11586  case SCIP_VARSTATUS_COLUMN:
11587  /* check for space in temporary memory */
11588  if( nactivevars >= activevarssize )
11589  {
11590  activevarssize *= 2;
11591  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11592  assert(nactivevars < activevarssize);
11593  }
11594  activevars[nactivevars] = var;
11595  nactivevars++;
11596  break;
11597 
11599  /* x = a_1*y_1 + ... + a_n*y_n + c */
11600  nmultvars = var->data.multaggr.nvars;
11601  multvars = var->data.multaggr.vars;
11602 
11603  /* check for space in temporary memory */
11604  if( nmultvars + ntmpvars > tmpvarssize )
11605  {
11606  while( nmultvars + ntmpvars > tmpvarssize )
11607  tmpvarssize *= 2;
11608  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11609  assert(nmultvars + ntmpvars <= tmpvarssize);
11610  }
11611 
11612  /* copy all multi-aggregation variables into our working array */
11613  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11614 
11615  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11616  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11617 
11618  ntmpvars += nmultvars;
11619  noldtmpvars = ntmpvars;
11620 
11621  /* sort all variables to combine equal variables easily */
11622  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11623  for( v = ntmpvars - 1; v > 0; --v )
11624  {
11625  /* combine same variables */
11626  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11627  {
11628  --ntmpvars;
11629  tmpvars[v] = tmpvars[ntmpvars];
11630  }
11631  }
11632  /* sort all variables again to combine equal variables later on */
11633  if( noldtmpvars > ntmpvars )
11634  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11635 
11636  break;
11637 
11638  case SCIP_VARSTATUS_FIXED:
11639  /* no need for memorizing fixed variables */
11640  break;
11641 
11642  default:
11643  SCIPerrorMessage("unknown variable status\n");
11644  SCIPABORT();
11645  return SCIP_INVALIDDATA; /*lint !e527*/
11646  }
11647  }
11648 
11649  /* sort variable array by variable index */
11650  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11651 
11652  /* eliminate duplicates and count required size */
11653  v = nactivevars - 1;
11654  while( v > 0 )
11655  {
11656  /* combine both variable since they are the same */
11657  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11658  {
11659  --nactivevars;
11660  activevars[v] = activevars[nactivevars];
11661  }
11662  --v;
11663  }
11664  *requiredsize = nactivevars;
11665 
11666  if( varssize >= *requiredsize )
11667  {
11668  assert(vars != NULL);
11669 
11670  *nvars = *requiredsize;
11671  BMScopyMemoryArray(vars, activevars, nactivevars);
11672  }
11673 
11674  SCIPsetFreeBufferArray(set, &tmpvars);
11675  SCIPsetFreeBufferArray(set, &activevars);
11676 
11677  return SCIP_OKAY;
11678 }
11679 
11680 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11681  * @note the content of the given array will/might change
11682  */
11683 void SCIPvarsGetProbvar(
11684  SCIP_VAR** vars, /**< array of problem variables */
11685  int nvars /**< number of variables */
11686  )
11687 {
11688  int v;
11689 
11690  assert(vars != NULL || nvars == 0);
11691 
11692  for( v = nvars - 1; v >= 0; --v )
11693  {
11694  assert(vars != NULL);
11695  assert(vars[v] != NULL);
11696 
11697  vars[v] = SCIPvarGetProbvar(vars[v]);
11698  assert(vars[v] != NULL);
11699  }
11700 }
11701 
11702 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11704  SCIP_VAR* var /**< problem variable */
11705  )
11706 {
11707  SCIP_VAR* retvar;
11708 
11709  assert(var != NULL);
11710 
11711  retvar = var;
11712 
11713  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11714 
11715  while( TRUE ) /*lint !e716 */
11716  {
11717  assert(retvar != NULL);
11718 
11719  switch( SCIPvarGetStatus(retvar) )
11720  {
11722  if( retvar->data.original.transvar == NULL )
11723  {
11724  SCIPerrorMessage("original variable has no transformed variable attached\n");
11725  SCIPABORT();
11726  return NULL; /*lint !e527 */
11727  }
11728  retvar = retvar->data.original.transvar;
11729  break;
11730 
11731  case SCIP_VARSTATUS_LOOSE:
11732  case SCIP_VARSTATUS_COLUMN:
11733  case SCIP_VARSTATUS_FIXED:
11734  return retvar;
11735 
11737  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11738  if ( retvar->data.multaggr.nvars == 1 )
11739  retvar = retvar->data.multaggr.vars[0];
11740  else
11741  return retvar;
11742  break;
11743 
11745  retvar = retvar->data.aggregate.var;
11746  break;
11747 
11749  retvar = retvar->negatedvar;
11750  break;
11751 
11752  default:
11753  SCIPerrorMessage("unknown variable status\n");
11754  SCIPABORT();
11755  return NULL; /*lint !e527*/
11756  }
11757  }
11758 }
11759 
11760 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11761  * negation status of each variable
11762  */
11764  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11765  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11766  int nvars /**< number of variables and values in vars and negated array */
11767  )
11768 {
11769  SCIP_VAR** var;
11770  SCIP_Bool* negated;
11771  int v;
11772 
11773  assert(vars != NULL);
11774  assert(*vars != NULL || nvars == 0);
11775  assert(negatedarr != NULL);
11776  assert(*negatedarr != NULL || nvars == 0);
11777 
11778  for( v = nvars - 1; v >= 0; --v )
11779  {
11780  var = &((*vars)[v]);
11781  negated = &((*negatedarr)[v]);
11782 
11783  /* get problem variable */
11784  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11785  }
11786 
11787  return SCIP_OKAY;
11788 }
11789 
11790 
11791 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11792  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11793  * FALSE is used)
11794  */
11796  SCIP_VAR** var, /**< pointer to binary problem variable */
11797  SCIP_Bool* negated /**< pointer to update the negation status */
11798  )
11799 {
11801 #ifndef NDEBUG
11802  SCIP_Real constant = 0.0;
11803  SCIP_Bool orignegated;
11804 #endif
11805 
11806  assert(var != NULL);
11807  assert(*var != NULL);
11808  assert(negated != NULL);
11809  assert(SCIPvarIsBinary(*var));
11810 
11811 #ifndef NDEBUG
11812  orignegated = *negated;
11813 #endif
11814 
11815  while( !active && *var != NULL )
11816  {
11817  switch( SCIPvarGetStatus(*var) )
11818  {
11820  if( (*var)->data.original.transvar == NULL )
11821  return SCIP_OKAY;
11822  *var = (*var)->data.original.transvar;
11823  break;
11824 
11825  case SCIP_VARSTATUS_LOOSE:
11826  case SCIP_VARSTATUS_COLUMN:
11827  case SCIP_VARSTATUS_FIXED:
11828  active = TRUE;
11829  break;
11830 
11832  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11833  if ( (*var)->data.multaggr.nvars == 1 )
11834  {
11835  assert( (*var)->data.multaggr.vars != NULL );
11836  assert( (*var)->data.multaggr.scalars != NULL );
11837  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11838  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11839 
11840  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11841  * another variable which needs to be fixed
11842  *
11843  * e.g. x = y - 1 => (x = 0 && y = 1)
11844  * e.g. x = y + 1 => (x = 1 && y = 0)
11845  *
11846  * is this special case we need to return the muti-aggregation
11847  */
11848  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)) )
11849  {
11850  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11851  }
11852  else
11853  {
11854  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11855  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11856  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11857  * we will return the aggregated variable;
11858  */
11859  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11860  {
11861  active = TRUE;
11862  break;
11863  }
11864 
11865  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11866  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11867  * so if this is the case, we will return the aggregated variable
11868  */
11869  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11870  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11871  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11872 
11873  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11874  {
11875  active = TRUE;
11876  break;
11877  }
11878 
11879  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11880 
11881  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11882  {
11883  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11884  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11885  * variable itself is multi-aggregated again?
11886  */
11887  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11888  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11889  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
11890  }
11891  else
11892  {
11893  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11894 #ifndef NDEBUG
11895  constant += (*negated) != orignegated ? -1.0 : 1.0;
11896 #endif
11897 
11898  *negated = !(*negated);
11899  }
11900  *var = (*var)->data.multaggr.vars[0];
11901  break;
11902  }
11903  }
11904  active = TRUE;
11905  break;
11906 
11907  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11908  assert((*var)->data.aggregate.var != NULL);
11909  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11910  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11911 #ifndef NDEBUG
11912  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11913 #endif
11914 
11915  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11916  *var = (*var)->data.aggregate.var;
11917  break;
11918 
11919  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11920  assert((*var)->negatedvar != NULL);
11921 #ifndef NDEBUG
11922  constant += (*negated) != orignegated ? -1.0 : 1.0;
11923 #endif
11924 
11925  *negated = !(*negated);
11926  *var = (*var)->negatedvar;
11927  break;
11928 
11929  default:
11930  SCIPerrorMessage("unknown variable status\n");
11931  return SCIP_INVALIDDATA;
11932  }
11933  }
11934  assert(active == (*var != NULL));
11935 
11936  if( active )
11937  {
11938  assert(SCIPvarIsBinary(*var));
11939  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11940  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11941 
11942  return SCIP_OKAY;
11943  }
11944  else
11945  {
11946  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11947  return SCIP_INVALIDDATA;
11948  }
11949 }
11950 
11951 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11952  * values
11953  */
11955  SCIP_VAR** var, /**< pointer to problem variable */
11956  SCIP_Real* bound, /**< pointer to bound value to transform */
11957  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11958  )
11959 {
11960  assert(var != NULL);
11961  assert(*var != NULL);
11962  assert(bound != NULL);
11963  assert(boundtype != NULL);
11964 
11965  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11966 
11967  switch( SCIPvarGetStatus(*var) )
11968  {
11970  if( (*var)->data.original.transvar == NULL )
11971  {
11972  SCIPerrorMessage("original variable has no transformed variable attached\n");
11973  return SCIP_INVALIDDATA;
11974  }
11975  *var = (*var)->data.original.transvar;
11976  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11977  break;
11978 
11979  case SCIP_VARSTATUS_LOOSE:
11980  case SCIP_VARSTATUS_COLUMN:
11981  case SCIP_VARSTATUS_FIXED:
11982  break;
11983 
11985  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11986  if ( (*var)->data.multaggr.nvars == 1 )
11987  {
11988  assert( (*var)->data.multaggr.vars != NULL );
11989  assert( (*var)->data.multaggr.scalars != NULL );
11990  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11991 
11992  (*bound) /= (*var)->data.multaggr.scalars[0];
11993  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11994  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11995  {
11996  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11997  *boundtype = SCIP_BOUNDTYPE_UPPER;
11998  else
11999  *boundtype = SCIP_BOUNDTYPE_LOWER;
12000  }
12001  *var = (*var)->data.multaggr.vars[0];
12002  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12003  }
12004  break;
12005 
12006  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12007  assert((*var)->data.aggregate.var != NULL);
12008  assert((*var)->data.aggregate.scalar != 0.0);
12009 
12010  (*bound) /= (*var)->data.aggregate.scalar;
12011  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12012  if( (*var)->data.aggregate.scalar < 0.0 )
12013  {
12014  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12015  *boundtype = SCIP_BOUNDTYPE_UPPER;
12016  else
12017  *boundtype = SCIP_BOUNDTYPE_LOWER;
12018  }
12019  *var = (*var)->data.aggregate.var;
12020  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12021  break;
12022 
12023  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12024  assert((*var)->negatedvar != NULL);
12025  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12026  assert((*var)->negatedvar->negatedvar == *var);
12027  (*bound) = (*var)->data.negate.constant - *bound;
12028  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12029  *boundtype = SCIP_BOUNDTYPE_UPPER;
12030  else
12031  *boundtype = SCIP_BOUNDTYPE_LOWER;
12032  *var = (*var)->negatedvar;
12033  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12034  break;
12035 
12036  default:
12037  SCIPerrorMessage("unknown variable status\n");
12038  return SCIP_INVALIDDATA;
12039  }
12040 
12041  return SCIP_OKAY;
12042 }
12043 
12044 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12045  * values
12046  */
12048  SCIP_VAR** var, /**< pointer to problem variable */
12049  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12050  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12051  )
12052 {
12053  assert(var != NULL);
12054  assert(*var != NULL);
12055  assert(left != NULL);
12056  assert(right != NULL);
12057 
12058  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12059 
12060  switch( SCIPvarGetStatus(*var) )
12061  {
12063  if( (*var)->data.original.transvar == NULL )
12064  {
12065  SCIPerrorMessage("original variable has no transformed variable attached\n");
12066  return SCIP_INVALIDDATA;
12067  }
12068  *var = (*var)->data.original.transvar;
12069  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12070  break;
12071 
12072  case SCIP_VARSTATUS_LOOSE:
12073  case SCIP_VARSTATUS_COLUMN:
12074  case SCIP_VARSTATUS_FIXED:
12076  break;
12077 
12078  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12079  assert((*var)->data.aggregate.var != NULL);
12080  assert((*var)->data.aggregate.scalar != 0.0);
12081 
12082  /* scale back */
12083  (*left) /= (*var)->data.aggregate.scalar;
12084  (*right) /= (*var)->data.aggregate.scalar;
12085 
12086  /* shift back */
12087  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12088  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12089 
12090  *var = (*var)->data.aggregate.var;
12091 
12092  /* check if the interval bounds have to swapped */
12093  if( (*var)->data.aggregate.scalar < 0.0 )
12094  {
12095  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12096  }
12097  else
12098  {
12099  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12100  }
12101  break;
12102 
12103  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12104  assert((*var)->negatedvar != NULL);
12105  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12106  assert((*var)->negatedvar->negatedvar == *var);
12107 
12108  /* shift and scale back */
12109  (*left) = (*var)->data.negate.constant - (*left);
12110  (*right) = (*var)->data.negate.constant - (*right);
12111 
12112  *var = (*var)->negatedvar;
12113 
12114  /* through the negated variable the left and right interval bound have to swapped */
12115  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12116  break;
12117 
12118  default:
12119  SCIPerrorMessage("unknown variable status\n");
12120  return SCIP_INVALIDDATA;
12121  }
12122 
12123  return SCIP_OKAY;
12124 }
12125 
12126 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12127  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12128  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12129  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12130  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12131  */
12133  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12134  SCIP_SET* set, /**< global SCIP settings */
12135  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12136  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12137  )
12138 {
12139  assert(var != NULL);
12140  assert(scalar != NULL);
12141  assert(constant != NULL);
12142 
12143  while( *var != NULL )
12144  {
12145  switch( SCIPvarGetStatus(*var) )
12146  {
12148  if( (*var)->data.original.transvar == NULL )
12149  {
12150  SCIPerrorMessage("original variable has no transformed variable attached\n");
12151  return SCIP_INVALIDDATA;
12152  }
12153  *var = (*var)->data.original.transvar;
12154  break;
12155 
12156  case SCIP_VARSTATUS_LOOSE:
12157  case SCIP_VARSTATUS_COLUMN:
12158  return SCIP_OKAY;
12159 
12160  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12161  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12162  {
12163  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12164  {
12165  assert(*scalar != 0.0);
12166  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12167  (*constant) = SCIPsetInfinity(set);
12168  else
12169  (*constant) = -SCIPsetInfinity(set);
12170  }
12171  else
12172  (*constant) += *scalar * (*var)->glbdom.lb;
12173  }
12174 #ifndef NDEBUG
12175  else
12176  {
12177  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12178  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12179  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12180  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12181  }
12182 #endif
12183  *scalar = 0.0;
12184  return SCIP_OKAY;
12185 
12187  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12188  if ( (*var)->data.multaggr.nvars == 1 )
12189  {
12190  assert((*var)->data.multaggr.vars != NULL);
12191  assert((*var)->data.multaggr.scalars != NULL);
12192  assert((*var)->data.multaggr.vars[0] != NULL);
12193  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12194  {
12195  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12196  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12197  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12198  */
12199  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12200  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12201  {
12202  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12203  {
12204  assert(!SCIPsetIsInfinity(set, -(*constant)));
12205  (*constant) = SCIPsetInfinity(set);
12206  }
12207  else
12208  {
12209  assert(!SCIPsetIsInfinity(set, *constant));
12210  (*constant) = -SCIPsetInfinity(set);
12211  }
12212  (*scalar) = 0.0;
12213  }
12214  else
12215  (*constant) += *scalar * (*var)->data.multaggr.constant;
12216  }
12217  (*scalar) *= (*var)->data.multaggr.scalars[0];
12218  *var = (*var)->data.multaggr.vars[0];
12219  break;
12220  }
12221  return SCIP_OKAY;
12222 
12223  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12224  assert((*var)->data.aggregate.var != NULL);
12225  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12226  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12227  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12228  (*constant) += *scalar * (*var)->data.aggregate.constant;
12229  (*scalar) *= (*var)->data.aggregate.scalar;
12230  *var = (*var)->data.aggregate.var;
12231  break;
12232 
12233  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12234  assert((*var)->negatedvar != NULL);
12235  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12236  assert((*var)->negatedvar->negatedvar == *var);
12237  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12238  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12239  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12240  (*constant) += *scalar * (*var)->data.negate.constant;
12241  (*scalar) *= -1.0;
12242  *var = (*var)->negatedvar;
12243  break;
12244 
12245  default:
12246  SCIPerrorMessage("unknown variable status\n");
12247  SCIPABORT();
12248  return SCIP_INVALIDDATA; /*lint !e527*/
12249  }
12250  }
12251  *scalar = 0.0;
12252 
12253  return SCIP_OKAY;
12254 }
12255 
12256 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12257  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12258  */
12260  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12261  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12262  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12263  )
12264 {
12265  SCIP_VAR* parentvar;
12266 
12267  assert(var != NULL);
12268  assert(*var != NULL);
12269  assert(scalar != NULL);
12270  assert(constant != NULL);
12271 
12272  while( !SCIPvarIsOriginal(*var) )
12273  {
12274  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12275  * var
12276  */
12277  if( (*var)->nparentvars == 0 )
12278  {
12279  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12280  * space
12281  */
12283  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12284  {
12285  *scalar *= -1.0;
12286  *constant -= (*var)->data.negate.constant * (*scalar);
12287  *var = (*var)->negatedvar;
12288 
12289  continue;
12290  }
12291  /* if the variables does not have any parent the variables was created during solving and has no original
12292  * counterpart
12293  */
12294  else
12295  {
12296  *var = NULL;
12297 
12298  return SCIP_OKAY;
12299  }
12300  }
12301 
12302  /* follow the link to the first parent variable */
12303  parentvar = (*var)->parentvars[0];
12304  assert(parentvar != NULL);
12305 
12306  switch( SCIPvarGetStatus(parentvar) )
12307  {
12309  break;
12310 
12311  case SCIP_VARSTATUS_COLUMN:
12312  case SCIP_VARSTATUS_LOOSE:
12313  case SCIP_VARSTATUS_FIXED:
12315  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12316  return SCIP_INVALIDDATA;
12317 
12318  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12319  assert(parentvar->data.aggregate.var == *var);
12320  assert(parentvar->data.aggregate.scalar != 0.0);
12321  *scalar /= parentvar->data.aggregate.scalar;
12322  *constant -= parentvar->data.aggregate.constant * (*scalar);
12323  break;
12324 
12325  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12326  assert(parentvar->negatedvar != NULL);
12327  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12328  assert(parentvar->negatedvar->negatedvar == parentvar);
12329  *scalar *= -1.0;
12330  *constant -= parentvar->data.negate.constant * (*scalar);
12331  break;
12332 
12333  default:
12334  SCIPerrorMessage("unknown variable status\n");
12335  return SCIP_INVALIDDATA;
12336  }
12337 
12338  assert( parentvar != NULL );
12339  *var = parentvar;
12340  }
12341 
12342  return SCIP_OKAY;
12343 }
12344 
12345 /** returns whether the given variable is the direct counterpart of an original problem variable */
12347  SCIP_VAR* var /**< problem variable */
12348  )
12349 {
12350  SCIP_VAR* parentvar;
12351  assert(var != NULL);
12352 
12353  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12354  return FALSE;
12355 
12356  assert(var->parentvars != NULL);
12357  parentvar = var->parentvars[0];
12358  assert(parentvar != NULL);
12359 
12360  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12361  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12362  parentvar = parentvar->parentvars[0];
12363  assert( parentvar != NULL );
12364 
12365  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12366 }
12367 
12368 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12369  * the variable's own data due to diving, that operate only on the LP without updating the variables
12370  */
12372  SCIP_VAR* var /**< problem variable */
12373  )
12374 {
12375  assert(var != NULL);
12376 
12377  /* get bounds of attached variables */
12378  switch( SCIPvarGetStatus(var) )
12379  {
12381  assert(var->data.original.transvar != NULL);
12382  return SCIPvarGetObjLP(var->data.original.transvar);
12383 
12384  case SCIP_VARSTATUS_COLUMN:
12385  assert(var->data.col != NULL);
12386  return SCIPcolGetObj(var->data.col);
12387 
12388  case SCIP_VARSTATUS_LOOSE:
12389  case SCIP_VARSTATUS_FIXED:
12390  return var->obj;
12391 
12392  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12393  assert(var->data.aggregate.var != NULL);
12394  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12395 
12397  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12398  SCIPABORT();
12399  return 0.0; /*lint !e527*/
12400 
12401  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12402  assert(var->negatedvar != NULL);
12404  assert(var->negatedvar->negatedvar == var);
12405  return -SCIPvarGetObjLP(var->negatedvar);
12406 
12407  default:
12408  SCIPerrorMessage("unknown variable status\n");
12409  SCIPABORT();
12410  return 0.0; /*lint !e527*/
12411  }
12412 }
12413 
12414 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12415  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12416  */
12418  SCIP_VAR* var, /**< problem variable */
12419  SCIP_SET* set /**< global SCIP settings */
12420  )
12421 {
12422  assert(var != NULL);
12423  assert(set != NULL);
12424  assert(var->scip == set->scip);
12425 
12426  /* get bounds of attached variables */
12427  switch( SCIPvarGetStatus(var) )
12428  {
12430  assert(var->data.original.transvar != NULL);
12431  return SCIPvarGetLbLP(var->data.original.transvar, set);
12432 
12433  case SCIP_VARSTATUS_COLUMN:
12434  assert(var->data.col != NULL);
12435  return SCIPcolGetLb(var->data.col);
12436 
12437  case SCIP_VARSTATUS_LOOSE:
12438  case SCIP_VARSTATUS_FIXED:
12439  return var->locdom.lb;
12440 
12441  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12442  assert(var->data.aggregate.var != NULL);
12443  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12444  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12445  {
12446  return -SCIPsetInfinity(set);
12447  }
12448  else if( var->data.aggregate.scalar > 0.0 )
12449  {
12450  /* a > 0 -> get lower bound of y */
12451  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12452  }
12453  else if( var->data.aggregate.scalar < 0.0 )
12454  {
12455  /* a < 0 -> get upper bound of y */
12456  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12457  }
12458  else
12459  {
12460  SCIPerrorMessage("scalar is zero in aggregation\n");
12461  SCIPABORT();
12462  return SCIP_INVALID; /*lint !e527*/
12463  }
12464 
12466  /**@todo get the sides of the corresponding linear constraint */
12467  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12468  SCIPABORT();
12469  return SCIP_INVALID; /*lint !e527*/
12470 
12471  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12472  assert(var->negatedvar != NULL);
12474  assert(var->negatedvar->negatedvar == var);
12475  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12476 
12477  default:
12478  SCIPerrorMessage("unknown variable status\n");
12479  SCIPABORT();
12480  return SCIP_INVALID; /*lint !e527*/
12481  }
12482 }
12483 
12484 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12485  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12486  */
12488  SCIP_VAR* var, /**< problem variable */
12489  SCIP_SET* set /**< global SCIP settings */
12490  )
12491 {
12492  assert(var != NULL);
12493  assert(set != NULL);
12494  assert(var->scip == set->scip);
12495 
12496  /* get bounds of attached variables */
12497  switch( SCIPvarGetStatus(var) )
12498  {
12500  assert(var->data.original.transvar != NULL);
12501  return SCIPvarGetUbLP(var->data.original.transvar, set);
12502 
12503  case SCIP_VARSTATUS_COLUMN:
12504  assert(var->data.col != NULL);
12505  return SCIPcolGetUb(var->data.col);
12506 
12507  case SCIP_VARSTATUS_LOOSE:
12508  case SCIP_VARSTATUS_FIXED:
12509  return var->locdom.ub;
12510 
12511  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12512  assert(var->data.aggregate.var != NULL);
12513  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12514  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12515  {
12516  return SCIPsetInfinity(set);
12517  }
12518  if( var->data.aggregate.scalar > 0.0 )
12519  {
12520  /* a > 0 -> get upper bound of y */
12521  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12522  }
12523  else if( var->data.aggregate.scalar < 0.0 )
12524  {
12525  /* a < 0 -> get lower bound of y */
12526  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12527  }
12528  else
12529  {
12530  SCIPerrorMessage("scalar is zero in aggregation\n");
12531  SCIPABORT();
12532  return SCIP_INVALID; /*lint !e527*/
12533  }
12534 
12536  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12537  SCIPABORT();
12538  return SCIP_INVALID; /*lint !e527*/
12539 
12540  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12541  assert(var->negatedvar != NULL);
12543  assert(var->negatedvar->negatedvar == var);
12544  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12545 
12546  default:
12547  SCIPerrorMessage("unknown variable status\n");
12548  SCIPABORT();
12549  return SCIP_INVALID; /*lint !e527*/
12550  }
12551 }
12552 
12553 /** gets primal LP solution value of variable */
12555  SCIP_VAR* var /**< problem variable */
12556  )
12557 {
12558  assert(var != NULL);
12559 
12560  switch( SCIPvarGetStatus(var) )
12561  {
12563  if( var->data.original.transvar == NULL )
12564  return SCIP_INVALID;
12565  return SCIPvarGetLPSol(var->data.original.transvar);
12566 
12567  case SCIP_VARSTATUS_LOOSE:
12568  return SCIPvarGetBestBoundLocal(var);
12569 
12570  case SCIP_VARSTATUS_COLUMN:
12571  assert(var->data.col != NULL);
12572  return SCIPcolGetPrimsol(var->data.col);
12573 
12574  case SCIP_VARSTATUS_FIXED:
12575  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12576  return var->locdom.lb;
12577 
12579  {
12580  SCIP_Real lpsolval;
12581 
12582  assert(var->data.aggregate.var != NULL);
12583  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12584 
12585  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12586  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12587  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12588  * (or is called by) a public interface method; instead, we only assert that values are finite
12589  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12590  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12591  */
12592  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12593  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12594  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12595  }
12597  {
12598  SCIP_Real primsol;
12599  int i;
12600 
12601  assert(!var->donotmultaggr);
12602  assert(var->data.multaggr.vars != NULL);
12603  assert(var->data.multaggr.scalars != NULL);
12604  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12605  * assert(var->data.multaggr.nvars >= 2);
12606  */
12607  primsol = var->data.multaggr.constant;
12608  for( i = 0; i < var->data.multaggr.nvars; ++i )
12609  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12610  return primsol;
12611  }
12612  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12613  assert(var->negatedvar != NULL);
12615  assert(var->negatedvar->negatedvar == var);
12616  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12617 
12618  default:
12619  SCIPerrorMessage("unknown variable status\n");
12620  SCIPABORT();
12621  return SCIP_INVALID; /*lint !e527*/
12622  }
12623 }
12624 
12625 /** gets primal NLP solution value of variable */
12627  SCIP_VAR* var /**< problem variable */
12628  )
12629 {
12630  SCIP_Real solval;
12631  int i;
12632 
12633  assert(var != NULL);
12634 
12635  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12636  switch( SCIPvarGetStatus(var) )
12637  {
12639  return SCIPvarGetNLPSol(var->data.original.transvar);
12640 
12641  case SCIP_VARSTATUS_LOOSE:
12642  case SCIP_VARSTATUS_COLUMN:
12643  return var->nlpsol;
12644 
12645  case SCIP_VARSTATUS_FIXED:
12646  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12647  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12648  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12649  return SCIPvarGetLbGlobal(var);
12650 
12651  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12652  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12653  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12654 
12656  solval = var->data.multaggr.constant;
12657  for( i = 0; i < var->data.multaggr.nvars; ++i )
12658  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12659  return solval;
12660 
12662  solval = SCIPvarGetNLPSol(var->negatedvar);
12663  return var->data.negate.constant - solval;
12664 
12665  default:
12666  SCIPerrorMessage("unknown variable status\n");
12667  SCIPABORT();
12668  return SCIP_INVALID; /*lint !e527*/
12669  }
12670 }
12671 
12672 /** gets pseudo solution value of variable at current node */
12673 static
12675  SCIP_VAR* var /**< problem variable */
12676  )
12677 {
12678  SCIP_Real pseudosol;
12679  int i;
12680 
12681  assert(var != NULL);
12682 
12683  switch( SCIPvarGetStatus(var) )
12684  {
12686  if( var->data.original.transvar == NULL )
12687  return SCIP_INVALID;
12689 
12690  case SCIP_VARSTATUS_LOOSE:
12691  case SCIP_VARSTATUS_COLUMN:
12692  return SCIPvarGetBestBoundLocal(var);
12693 
12694  case SCIP_VARSTATUS_FIXED:
12695  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12696  return var->locdom.lb;
12697 
12699  {
12700  SCIP_Real pseudosolval;
12701  assert(var->data.aggregate.var != NULL);
12702  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12703  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12704  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12705  * (or is called by) a public interface method; instead, we only assert that values are finite
12706  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12707  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12708  */
12709  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12710  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12711  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12712  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12713  }
12715  assert(!var->donotmultaggr);
12716  assert(var->data.multaggr.vars != NULL);
12717  assert(var->data.multaggr.scalars != NULL);
12718  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12719  * assert(var->data.multaggr.nvars >= 2);
12720  */
12721  pseudosol = var->data.multaggr.constant;
12722  for( i = 0; i < var->data.multaggr.nvars; ++i )
12723  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12724  return pseudosol;
12725 
12726  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12727  assert(var->negatedvar != NULL);
12729  assert(var->negatedvar->negatedvar == var);
12730  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12731 
12732  default:
12733  SCIPerrorMessage("unknown variable status\n");
12734  SCIPABORT();
12735  return SCIP_INVALID; /*lint !e527*/
12736  }
12737 }
12738 
12739 /** gets current LP or pseudo solution value of variable */
12741  SCIP_VAR* var, /**< problem variable */
12742  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12743  )
12744 {
12745  if( getlpval )
12746  return SCIPvarGetLPSol(var);
12747  else
12748  return SCIPvarGetPseudoSol(var);
12749 }
12750 
12751 /** remembers the current solution as root solution in the problem variables */
12752 void SCIPvarStoreRootSol(
12753  SCIP_VAR* var, /**< problem variable */
12754  SCIP_Bool roothaslp /**< is the root solution from LP? */
12755  )
12756 {
12757  assert(var != NULL);
12758 
12759  var->rootsol = SCIPvarGetSol(var, roothaslp);
12760 }
12761 
12762 /** updates the current solution as best root solution of the given variable if it is better */
12764  SCIP_VAR* var, /**< problem variable */
12765  SCIP_SET* set, /**< global SCIP settings */
12766  SCIP_Real rootsol, /**< root solution value */
12767  SCIP_Real rootredcost, /**< root reduced cost */
12768  SCIP_Real rootlpobjval /**< objective value of the root LP */
12769  )
12770 {
12771  assert(var != NULL);
12772  assert(set != NULL);
12773  assert(var->scip == set->scip);
12774 
12775  /* if reduced cost are zero nothing to update */
12776  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12777  return;
12778 
12779  /* check if we have already a best combination stored */
12780  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12781  {
12782  SCIP_Real currcutoffbound;
12783  SCIP_Real cutoffbound;
12784  SCIP_Real bound;
12785 
12786  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12787  * root reduced cost, and root LP objective value combination
12788  */
12789  if( var->bestrootredcost > 0.0 )
12790  bound = SCIPvarGetUbGlobal(var);
12791  else
12792  bound = SCIPvarGetLbGlobal(var);
12793 
12794  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12795 
12796  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12797  * cost, and root LP objective value combination
12798  */
12799  if( rootredcost > 0.0 )
12800  bound = SCIPvarGetUbGlobal(var);
12801  else
12802  bound = SCIPvarGetLbGlobal(var);
12803 
12804  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12805 
12806  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12807  if( cutoffbound > currcutoffbound )
12808  {
12809  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12810  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12811 
12812  var->bestrootsol = rootsol;
12813  var->bestrootredcost = rootredcost;
12814  var->bestrootlpobjval = rootlpobjval;
12815  }
12816  }
12817  else
12818  {
12819  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12820  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12821  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12822  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12823 
12824  var->bestrootsol = rootsol;
12825  var->bestrootredcost = rootredcost;
12826  var->bestrootlpobjval = rootlpobjval;
12827  }
12828 }
12829 
12830 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12831  * completely solved, zero is returned
12832  */
12834  SCIP_VAR* var /**< problem variable */
12835  )
12836 {
12837  SCIP_Real rootsol;
12838  int i;
12839 
12840  assert(var != NULL);
12841 
12842  switch( SCIPvarGetStatus(var) )
12843  {
12845  if( var->data.original.transvar == NULL )
12846  return 0.0;
12847  return SCIPvarGetRootSol(var->data.original.transvar);
12848 
12849  case SCIP_VARSTATUS_LOOSE:
12850  case SCIP_VARSTATUS_COLUMN:
12851  return var->rootsol;
12852 
12853  case SCIP_VARSTATUS_FIXED:
12854  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12855  return var->locdom.lb;
12856 
12858  assert(var->data.aggregate.var != NULL);
12859  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12860  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12861  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12862  * (or is called by) a public interface method; instead, we only assert that values are finite
12863  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12864  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12865  */
12869 
12871  assert(!var->donotmultaggr);
12872  assert(var->data.multaggr.vars != NULL);
12873  assert(var->data.multaggr.scalars != NULL);
12874  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12875  * assert(var->data.multaggr.nvars >= 2);
12876  */
12877  rootsol = var->data.multaggr.constant;
12878  for( i = 0; i < var->data.multaggr.nvars; ++i )
12879  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12880  return rootsol;
12881 
12882  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12883  assert(var->negatedvar != NULL);
12885  assert(var->negatedvar->negatedvar == var);
12886  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12887 
12888  default:
12889  SCIPerrorMessage("unknown variable status\n");
12890  SCIPABORT();
12891  return SCIP_INVALID; /*lint !e527*/
12892  }
12893 }
12894 
12895 /** returns for given variable the reduced cost */
12896 static
12898  SCIP_VAR* var, /**< problem variable */
12899  SCIP_SET* set, /**< global SCIP settings */
12900  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12901  SCIP_STAT* stat, /**< problem statistics */
12902  SCIP_LP* lp /**< current LP data */
12903  )
12904 {
12906  {
12907  SCIP_COL* col;
12908  SCIP_Real primsol;
12909  SCIP_BASESTAT basestat;
12910  SCIP_Bool lpissolbasic;
12911 
12912  col = SCIPvarGetCol(var);
12913  assert(col != NULL);
12914 
12915  basestat = SCIPcolGetBasisStatus(col);
12916  lpissolbasic = SCIPlpIsSolBasic(lp);
12917  primsol = SCIPcolGetPrimsol(col);
12918 
12919  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12920  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12921  {
12922  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12923 
12924  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12925  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12927  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12928  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12929  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12930 
12931  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12932  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12933  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12934  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12935  return redcost;
12936  else
12937  return 0.0;
12938  }
12939 
12940  return 0.0;
12941  }
12942 
12943  return 0.0;
12944 }
12945 
12946 #define MAX_CLIQUELENGTH 50
12947 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12948  * the binary variable is fixed to the given value
12949  */
12951  SCIP_VAR* var, /**< problem variable */
12952  SCIP_SET* set, /**< global SCIP settings */
12953  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12954  SCIP_STAT* stat, /**< problem statistics */
12955  SCIP_PROB* prob, /**< transformed problem, or NULL */
12956  SCIP_LP* lp /**< current LP data */
12957  )
12958 {
12959  SCIP_Real implredcost;
12960  int ncliques;
12961  int nvars;
12962 
12963  assert(SCIPvarIsBinary(var));
12964  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12965 
12966  /* get reduced cost of given variable */
12967  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12968 
12969 #ifdef SCIP_MORE_DEBUG
12970  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12971 #endif
12972 
12973  /* the following algorithm is expensive */
12974  ncliques = SCIPvarGetNCliques(var, varfixing);
12975 
12976  if( ncliques > 0 )
12977  {
12978  SCIP_CLIQUE** cliques;
12979  SCIP_CLIQUE* clique;
12980  SCIP_VAR** clqvars;
12981  SCIP_VAR** probvars;
12982  SCIP_VAR* clqvar;
12983  SCIP_Bool* clqvalues;
12984  int* entries;
12985  int* ids;
12986  SCIP_Real redcost;
12987  SCIP_Bool cleanedup;
12988  int nclqvars;
12989  int nentries;
12990  int nids;
12991  int id;
12992  int c;
12993  int v;
12994 
12995  assert(prob != NULL);
12996  assert(SCIPprobIsTransformed(prob));
12997 
12998  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12999 
13000  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13001  nids = 0;
13002  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13003 
13004  cliques = SCIPvarGetCliques(var, varfixing);
13005  assert(cliques != NULL);
13006 
13007  for( c = ncliques - 1; c >= 0; --c )
13008  {
13009  clique = cliques[c];
13010  assert(clique != NULL);
13011  nclqvars = SCIPcliqueGetNVars(clique);
13012  assert(nclqvars > 0);
13013 
13014  if( nclqvars > MAX_CLIQUELENGTH )
13015  continue;
13016 
13017  clqvars = SCIPcliqueGetVars(clique);
13018  clqvalues = SCIPcliqueGetValues(clique);
13019  assert(clqvars != NULL);
13020  assert(clqvalues != NULL);
13021 
13022  cleanedup = SCIPcliqueIsCleanedUp(clique);
13023 
13024  for( v = nclqvars - 1; v >= 0; --v )
13025  {
13026  clqvar = clqvars[v];
13027  assert(clqvar != NULL);
13028 
13029  /* ignore binary variable which are fixed */
13030  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13031  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13032  {
13033  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13034  assert(0 < probindex && probindex < nentries);
13035 
13036 #if 0
13037  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13038  * can appear since there is no guarantee that all these infeasible bounds were found
13039  */
13040  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13041 #endif
13042  if( entries[probindex] == 0 )
13043  {
13044  ids[nids] = probindex;
13045  ++nids;
13046 
13047  /* mark variable as visited */
13048  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13049  }
13050  }
13051  }
13052  }
13053 
13054  probvars = SCIPprobGetVars(prob);
13055  assert(probvars != NULL);
13056 
13057  /* add all implied reduced cost */
13058  for( v = nids - 1; v >= 0; --v )
13059  {
13060  id = ids[v];
13061  assert(0 < id && id < nentries);
13062  assert(entries[id] != 0);
13063  assert(probvars[id - 1] != NULL);
13064  assert(SCIPvarIsActive(probvars[id - 1]));
13065  assert(SCIPvarIsBinary(probvars[id - 1]));
13066  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13067 
13068  if( (entries[id] > 0) != varfixing )
13069  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13070  else
13071  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13072 
13073  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13074  implredcost += redcost;
13075 
13076  /* reset entries clear buffer array */
13077  entries[id] = 0;
13078  }
13079 
13080  SCIPsetFreeCleanBufferArray(set, &entries);
13081  SCIPsetFreeBufferArray(set, &ids);
13082  }
13083 
13084 #ifdef SCIP_MORE_DEBUG
13085  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13086  implredcost);
13087 #endif
13088 
13089  /* collect non-binary implication information */
13090  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13091 
13092  if( nvars > 0 )
13093  {
13094  SCIP_VAR** vars;
13095  SCIP_VAR* implvar;
13096  SCIP_COL* col;
13097  SCIP_Real* bounds;
13098  SCIP_BOUNDTYPE* boundtypes;
13099  SCIP_Real redcost;
13100  SCIP_Real lb;
13101  SCIP_Real ub;
13102  SCIP_Bool lpissolbasic;
13103  int v;
13104 
13105  vars = SCIPimplicsGetVars(var->implics, varfixing);
13106  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13107  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13108  lpissolbasic = SCIPlpIsSolBasic(lp);
13109 
13110  for( v = nvars - 1; v >= 0; --v )
13111  {
13112  implvar = vars[v];
13113  assert(implvar != NULL);
13114 
13115  lb = SCIPvarGetLbLocal(implvar);
13116  ub = SCIPvarGetUbLocal(implvar);
13117 
13118  /* ignore binary variable which are fixed or not of column status */
13119  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13120  continue;
13121 
13122  col = SCIPvarGetCol(implvar);
13123  assert(col != NULL);
13124  redcost = 0.0;
13125 
13126  /* solved lp with basis information or not? */
13127  if( lpissolbasic )
13128  {
13129  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13130 
13131  /* check if the implication is not not yet applied */
13132  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13133  {
13134  redcost = SCIPcolGetRedcost(col, stat, lp);
13135  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13136 
13137  if( !varfixing )
13138  redcost *= (lb - bounds[v]);
13139  else
13140  redcost *= (bounds[v] - lb);
13141  }
13142  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13143  {
13144  redcost = SCIPcolGetRedcost(col, stat, lp);
13145  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13146 
13147  if( varfixing )
13148  redcost *= (bounds[v] - ub);
13149  else
13150  redcost *= (ub - bounds[v]);
13151  }
13152  }
13153  else
13154  {
13155  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13156 
13157  /* check if the implication is not not yet applied */
13158  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13159  {
13160  redcost = SCIPcolGetRedcost(col, stat, lp);
13161  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13162 
13163  if( varfixing )
13164  redcost *= (lb - bounds[v]);
13165  else
13166  redcost *= (bounds[v] - lb);
13167  }
13168  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13169  {
13170  redcost = SCIPcolGetRedcost(col, stat, lp);
13171  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13172 
13173  if( varfixing )
13174  redcost *= (bounds[v] - ub);
13175  else
13176  redcost *= (ub - bounds[v]);
13177  }
13178  }
13179 
13180  /* improve implied reduced cost */
13181  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13182  implredcost += redcost;
13183  }
13184  }
13185 
13186 #ifdef SCIP_MORE_DEBUG
13187  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13188  SCIPvarGetName(var), ncliques, nvars, implredcost);
13189 #endif
13190 
13191  return implredcost;
13192 }
13193 
13194 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13195  * the root relaxation is not yet completely solved, zero is returned
13196  */
13198  SCIP_VAR* var /**< problem variable */
13199  )
13200 {
13201  SCIP_Real rootsol;
13202  int i;
13203 
13204  assert(var != NULL);
13205 
13206  switch( SCIPvarGetStatus(var) )
13207  {
13209  if( var->data.original.transvar == NULL )
13210  return 0.0;
13212 
13213  case SCIP_VARSTATUS_LOOSE:
13214  case SCIP_VARSTATUS_COLUMN:
13215  return var->bestrootsol;
13216 
13217  case SCIP_VARSTATUS_FIXED:
13218  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13219  return var->locdom.lb;
13220 
13222  assert(var->data.aggregate.var != NULL);
13223  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13224  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13225  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13226  * (or is called by) a public interface method; instead, we only assert that values are finite
13227  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13228  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13229  */
13233 
13235  assert(!var->donotmultaggr);
13236  assert(var->data.multaggr.vars != NULL);
13237  assert(var->data.multaggr.scalars != NULL);
13238  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13239  * assert(var->data.multaggr.nvars >= 2);
13240  */
13241  rootsol = var->data.multaggr.constant;
13242  for( i = 0; i < var->data.multaggr.nvars; ++i )
13243  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13244  return rootsol;
13245 
13246  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13247  assert(var->negatedvar != NULL);
13249  assert(var->negatedvar->negatedvar == var);
13250  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13251 
13252  default:
13253  SCIPerrorMessage("unknown variable status\n");
13254  SCIPABORT();
13255  return 0.0; /*lint !e527*/
13256  }
13257 }
13258 
13259 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13260  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13261  * returned
13262  */
13264  SCIP_VAR* var /**< problem variable */
13265  )
13266 {
13267  assert(var != NULL);
13268 
13269  switch( SCIPvarGetStatus(var) )
13270  {
13272  if( var->data.original.transvar == NULL )
13273  return SCIP_INVALID;
13275 
13276  case SCIP_VARSTATUS_LOOSE:
13277  case SCIP_VARSTATUS_COLUMN:
13278  return var->bestrootredcost;
13279 
13280  case SCIP_VARSTATUS_FIXED:
13284  return 0.0;
13285 
13286  default:
13287  SCIPerrorMessage("unknown variable status\n");
13288  SCIPABORT();
13289  return 0.0; /*lint !e527*/
13290  }
13291 }
13292 
13293 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13294  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13295  * SCIP_INVALID is returned
13296  */
13298  SCIP_VAR* var /**< problem variable */
13299  )
13300 {
13301  assert(var != NULL);
13302 
13303  switch( SCIPvarGetStatus(var) )
13304  {
13306  if( var->data.original.transvar == NULL )
13307  return SCIP_INVALID;
13309 
13310  case SCIP_VARSTATUS_LOOSE:
13311  case SCIP_VARSTATUS_COLUMN:
13312  return var->bestrootlpobjval;
13313 
13314  case SCIP_VARSTATUS_FIXED:
13318  return SCIP_INVALID;
13319 
13320  default:
13321  SCIPerrorMessage("unknown variable status\n");
13322  SCIPABORT();
13323  return SCIP_INVALID; /*lint !e527*/
13324  }
13325 }
13326 
13327 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13329  SCIP_VAR* var, /**< problem variable */
13330  SCIP_Real rootsol, /**< root solution value */
13331  SCIP_Real rootredcost, /**< root reduced cost */
13332  SCIP_Real rootlpobjval /**< objective value of the root LP */
13333  )
13334 {
13335  assert(var != NULL);
13336 
13337  var->bestrootsol = rootsol;
13338  var->bestrootredcost = rootredcost;
13339  var->bestrootlpobjval = rootlpobjval;
13340 }
13341 
13342 /** stores the solution value as relaxation solution in the problem variable */
13344  SCIP_VAR* var, /**< problem variable */
13345  SCIP_SET* set, /**< global SCIP settings */
13346  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13347  SCIP_Real solval, /**< solution value in the current relaxation solution */
13348  SCIP_Bool updateobj /**< should the objective value be updated? */
13349  )
13350 {
13351  assert(var != NULL);
13352  assert(relaxation != NULL);
13353  assert(set != NULL);
13354  assert(var->scip == set->scip);
13355 
13356  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13357  switch( SCIPvarGetStatus(var) )
13358  {
13360  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13361  break;
13362 
13363  case SCIP_VARSTATUS_LOOSE:
13364  case SCIP_VARSTATUS_COLUMN:
13365  if( updateobj )
13366  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13367  var->relaxsol = solval;
13368  break;
13369 
13370  case SCIP_VARSTATUS_FIXED:
13371  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13372  {
13373  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13374  SCIPvarGetName(var), var->glbdom.lb, solval);
13375  return SCIP_INVALIDDATA;
13376  }
13377  break;
13378 
13379  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13380  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13381  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13382  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13383  break;
13385  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13386  return SCIP_INVALIDDATA;
13387 
13389  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13390  break;
13391 
13392  default:
13393  SCIPerrorMessage("unknown variable status\n");
13394  return SCIP_INVALIDDATA;
13395  }
13396 
13397  return SCIP_OKAY;
13398 }
13399 
13400 /** returns the solution value of the problem variable in the relaxation solution
13401  *
13402  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13403  */
13405  SCIP_VAR* var, /**< problem variable */
13406  SCIP_SET* set /**< global SCIP settings */
13407  )
13408 {
13409  SCIP_Real solvalsum;
13410  SCIP_Real solval;
13411  int i;
13412 
13413  assert(var != NULL);
13414  assert(set != NULL);
13415  assert(var->scip == set->scip);
13416 
13417  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13418  switch( SCIPvarGetStatus(var) )
13419  {
13421  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13422 
13423  case SCIP_VARSTATUS_LOOSE:
13424  case SCIP_VARSTATUS_COLUMN:
13425  return var->relaxsol;
13426 
13427  case SCIP_VARSTATUS_FIXED:
13428  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13429  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13430  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13431  return SCIPvarGetLbGlobal(var);
13432 
13433  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13434  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13435  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13436  {
13437  if( var->data.aggregate.scalar * solval > 0.0 )
13438  return SCIPsetInfinity(set);
13439  if( var->data.aggregate.scalar * solval < 0.0 )
13440  return -SCIPsetInfinity(set);
13441  }
13442  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13443 
13445  solvalsum = var->data.multaggr.constant;
13446  for( i = 0; i < var->data.multaggr.nvars; ++i )
13447  {
13448  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13449  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13450  {
13451  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13452  return SCIPsetInfinity(set);
13453  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13454  return -SCIPsetInfinity(set);
13455  }
13456  solvalsum += var->data.multaggr.scalars[i] * solval;
13457  }
13458  return solvalsum;
13459 
13461  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13462  if( SCIPsetIsInfinity(set, solval) )
13463  return -SCIPsetInfinity(set);
13464  if( SCIPsetIsInfinity(set, -solval) )
13465  return SCIPsetInfinity(set);
13466  return var->data.negate.constant - solval;
13467 
13468  default:
13469  SCIPerrorMessage("unknown variable status\n");
13470  SCIPABORT();
13471  return SCIP_INVALID; /*lint !e527*/
13472  }
13473 }
13474 
13475 /** returns the solution value of the transformed problem variable in the relaxation solution */
13477  SCIP_VAR* var /**< problem variable */
13478  )
13479 {
13480  assert(var != NULL);
13482 
13483  return var->relaxsol;
13484 }
13485 
13486 /** stores the solution value as NLP solution in the problem variable */
13488  SCIP_VAR* var, /**< problem variable */
13489  SCIP_SET* set, /**< global SCIP settings */
13490  SCIP_Real solval /**< solution value in the current NLP solution */
13491  )
13492 {
13493  assert(var != NULL);
13494  assert(set != NULL);
13495  assert(var->scip == set->scip);
13496 
13497  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13498  switch( SCIPvarGetStatus(var) )
13499  {
13501  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13502  break;
13503 
13504  case SCIP_VARSTATUS_LOOSE:
13505  case SCIP_VARSTATUS_COLUMN:
13506  var->nlpsol = solval;
13507  break;
13508 
13509  case SCIP_VARSTATUS_FIXED:
13510  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13511  {
13512  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13513  SCIPvarGetName(var), var->glbdom.lb, solval);
13514  SCIPABORT();
13515  return SCIP_INVALIDCALL; /*lint !e527*/
13516  }
13517  break;
13518 
13519  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13520  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13521  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13522  break;
13523 
13525  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13526  SCIPABORT();
13527  return SCIP_INVALIDCALL; /*lint !e527*/
13528 
13530  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13531  break;
13532 
13533  default:
13534  SCIPerrorMessage("unknown variable status\n");
13535  SCIPABORT();
13536  return SCIP_ERROR; /*lint !e527*/
13537  }
13538 
13539  return SCIP_OKAY;
13540 }
13541 
13542 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13544  SCIP_VAR* var /**< problem variable */
13545  )
13546 {
13547  SCIP_Real avgsol;
13548  int i;
13549 
13550  assert(var != NULL);
13551 
13552  switch( SCIPvarGetStatus(var) )
13553  {
13555  if( var->data.original.transvar == NULL )
13556  return 0.0;
13557  return SCIPvarGetAvgSol(var->data.original.transvar);
13558 
13559  case SCIP_VARSTATUS_LOOSE:
13560  case SCIP_VARSTATUS_COLUMN:
13561  avgsol = var->primsolavg;
13562  avgsol = MAX(avgsol, var->glbdom.lb);
13563  avgsol = MIN(avgsol, var->glbdom.ub);
13564  return avgsol;
13565 
13566  case SCIP_VARSTATUS_FIXED:
13567  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13568  return var->locdom.lb;
13569 
13571  assert(var->data.aggregate.var != NULL);
13572  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13573  + var->data.aggregate.constant;
13574 
13576  assert(!var->donotmultaggr);
13577  assert(var->data.multaggr.vars != NULL);
13578  assert(var->data.multaggr.scalars != NULL);
13579  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13580  * assert(var->data.multaggr.nvars >= 2);
13581  */
13582  avgsol = var->data.multaggr.constant;
13583  for( i = 0; i < var->data.multaggr.nvars; ++i )
13584  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13585  return avgsol;
13586 
13587  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13588  assert(var->negatedvar != NULL);
13590  assert(var->negatedvar->negatedvar == var);
13591  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13592 
13593  default:
13594  SCIPerrorMessage("unknown variable status\n");
13595  SCIPABORT();
13596  return 0.0; /*lint !e527*/
13597  }
13598 }
13599 
13600 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13601  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13602  */
13604  SCIP_VAR* var, /**< active problem variable */
13605  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13606  SCIP_SET* set, /**< global SCIP settings */
13607  SCIP_STAT* stat, /**< problem statistics */
13608  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13609  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13610  )
13611 {
13612  int nvlbs;
13613 
13614  assert(var != NULL);
13615  assert(stat != NULL);
13616  assert(set != NULL);
13617  assert(var->scip == set->scip);
13618  assert(closestvlb != NULL);
13619  assert(closestvlbidx != NULL);
13620 
13621  *closestvlbidx = -1;
13622  *closestvlb = SCIP_REAL_MIN;
13623 
13624  nvlbs = SCIPvarGetNVlbs(var);
13625  if( nvlbs > 0 )
13626  {
13627  SCIP_VAR** vlbvars;
13628  SCIP_Real* vlbcoefs;
13629  SCIP_Real* vlbconsts;
13630  int i;
13631 
13632  vlbvars = SCIPvarGetVlbVars(var);
13633  vlbcoefs = SCIPvarGetVlbCoefs(var);
13634  vlbconsts = SCIPvarGetVlbConstants(var);
13635 
13636  /* check for cached values */
13637  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13638  {
13639  i = var->closestvlbidx;
13640  assert(0 <= i && i < nvlbs);
13641  assert(SCIPvarIsActive(vlbvars[i]));
13642  *closestvlbidx = i;
13643  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13644  }
13645  else
13646  {
13647  /* search best VUB */
13648  for( i = 0; i < nvlbs; i++ )
13649  {
13650  if( SCIPvarIsActive(vlbvars[i]) )
13651  {
13652  SCIP_Real vlbsol;
13653 
13654  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13655  if( vlbsol > *closestvlb )
13656  {
13657  *closestvlb = vlbsol;
13658  *closestvlbidx = i;
13659  }
13660  }
13661  }
13662 
13663  if( sol == NULL )
13664  {
13665  /* update cached value */
13666  if( var->closestvblpcount != stat->lpcount )
13667  var->closestvubidx = -1;
13668  var->closestvlbidx = *closestvlbidx;
13669  var->closestvblpcount = stat->lpcount;
13670  }
13671  }
13672  }
13673 }
13674 
13675 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13676  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13677  */
13679  SCIP_VAR* var, /**< active problem variable */
13680  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13681  SCIP_SET* set, /**< global SCIP settings */
13682  SCIP_STAT* stat, /**< problem statistics */
13683  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13684  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13685  )
13686 {
13687  int nvubs;
13688 
13689  assert(var != NULL);
13690  assert(set != NULL);
13691  assert(var->scip == set->scip);
13692  assert(closestvub != NULL);
13693  assert(closestvubidx != NULL);
13694 
13695  *closestvubidx = -1;
13696  *closestvub = SCIP_REAL_MAX;
13697 
13698  nvubs = SCIPvarGetNVubs(var);
13699  if( nvubs > 0 )
13700  {
13701  SCIP_VAR** vubvars;
13702  SCIP_Real* vubcoefs;
13703  SCIP_Real* vubconsts;
13704  int i;
13705 
13706  vubvars = SCIPvarGetVubVars(var);
13707  vubcoefs = SCIPvarGetVubCoefs(var);
13708  vubconsts = SCIPvarGetVubConstants(var);
13709 
13710  /* check for cached values */
13711  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13712  {
13713  i = var->closestvubidx;
13714  assert(0 <= i && i < nvubs);
13715  assert(SCIPvarIsActive(vubvars[i]));
13716  *closestvubidx = i;
13717  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13718  }
13719  else
13720  {
13721  /* search best VUB */
13722  for( i = 0; i < nvubs; i++ )
13723  {
13724  if( SCIPvarIsActive(vubvars[i]) )
13725  {
13726  SCIP_Real vubsol;
13727 
13728  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13729  if( vubsol < *closestvub )
13730  {
13731  *closestvub = vubsol;
13732  *closestvubidx = i;
13733  }
13734  }
13735  }
13736 
13737  if( sol == NULL )
13738  {
13739  /* update cached value */
13740  if( var->closestvblpcount != stat->lpcount )
13741  var->closestvlbidx = -1;
13742  var->closestvubidx = *closestvubidx;
13743  var->closestvblpcount = stat->lpcount;
13744  }
13745  }
13746  }
13747 }
13748 
13749 /** resolves variable to columns and adds them with the coefficient to the row */
13751  SCIP_VAR* var, /**< problem variable */
13752  BMS_BLKMEM* blkmem, /**< block memory */
13753  SCIP_SET* set, /**< global SCIP settings */
13754  SCIP_STAT* stat, /**< problem statistics */
13755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13756  SCIP_PROB* prob, /**< problem data */
13757  SCIP_LP* lp, /**< current LP data */
13758  SCIP_ROW* row, /**< LP row */
13759  SCIP_Real val /**< value of coefficient */
13760  )
13761 {
13762  int i;
13763 
13764  assert(var != NULL);
13765  assert(set != NULL);
13766  assert(var->scip == set->scip);
13767  assert(row != NULL);
13768  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13769 
13770  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13771 
13772  if ( SCIPsetIsZero(set, val) )
13773  return SCIP_OKAY;
13774 
13775  switch( SCIPvarGetStatus(var) )
13776  {
13778  if( var->data.original.transvar == NULL )
13779  {
13780  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13781  return SCIP_INVALIDDATA;
13782  }
13783  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13784  return SCIP_OKAY;
13785 
13786  case SCIP_VARSTATUS_LOOSE:
13787  /* add globally fixed variables as constant */
13788  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13789  {
13790  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13791  return SCIP_OKAY;
13792  }
13793  /* convert loose variable into column */
13794  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13795  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13796  /*lint -fallthrough*/
13797 
13798  case SCIP_VARSTATUS_COLUMN:
13799  assert(var->data.col != NULL);
13800  assert(var->data.col->var == var);
13801  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13802  return SCIP_OKAY;
13803 
13804  case SCIP_VARSTATUS_FIXED:
13805  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13806  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13807  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13808  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13809  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13810  return SCIP_OKAY;
13811 
13813  assert(var->data.aggregate.var != NULL);
13814  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13815  row, var->data.aggregate.scalar * val) );
13816  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13817  return SCIP_OKAY;
13818 
13820  assert(!var->donotmultaggr);
13821  assert(var->data.multaggr.vars != NULL);
13822  assert(var->data.multaggr.scalars != NULL);
13823  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13824  * assert(var->data.multaggr.nvars >= 2);
13825  */
13826  for( i = 0; i < var->data.multaggr.nvars; ++i )
13827  {
13828  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13829  row, var->data.multaggr.scalars[i] * val) );
13830  }
13831  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13832  return SCIP_OKAY;
13833 
13834  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13835  assert(var->negatedvar != NULL);
13837  assert(var->negatedvar->negatedvar == var);
13838  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13839  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13840  return SCIP_OKAY;
13841 
13842  default:
13843  SCIPerrorMessage("unknown variable status\n");
13844  return SCIP_INVALIDDATA;
13845  }
13846 }
13847 
13848 /* optionally, define this compiler flag to write complete variable histories to a file */
13849 #ifdef SCIP_HISTORYTOFILE
13850 SCIP_Longint counter = 0l;
13851 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13852 #include "scip/scip.h"
13853 #endif
13854 
13855 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13856  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13857  */
13859  SCIP_VAR* var, /**< problem variable */
13860  SCIP_SET* set, /**< global SCIP settings */
13861  SCIP_STAT* stat, /**< problem statistics */
13862  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13863  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13864  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13865  )
13866 {
13867  SCIP_Real oldrootpseudocosts;
13868  assert(var != NULL);
13869  assert(set != NULL);
13870  assert(var->scip == set->scip);
13871  assert(stat != NULL);
13872 
13873  /* check if history statistics should be collected for a variable */
13874  if( !stat->collectvarhistory )
13875  return SCIP_OKAY;
13876 
13877  switch( SCIPvarGetStatus(var) )
13878  {
13880  if( var->data.original.transvar == NULL )
13881  {
13882  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13883  return SCIP_INVALIDDATA;
13884  }
13885  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13886  return SCIP_OKAY;
13887 
13888  case SCIP_VARSTATUS_LOOSE:
13889  case SCIP_VARSTATUS_COLUMN:
13890  /* store old pseudo-costs for root LP best-estimate update */
13891  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13892 
13893  /* update history */
13894  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13895  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13896  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13897  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13898 
13899  /* update root LP best-estimate */
13900  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13901 
13902  /* append history to file */
13903 #ifdef SCIP_HISTORYTOFILE
13904  {
13905  FILE* f;
13906  char filename[256];
13907  SCIP_NODE* currentnode;
13908  SCIP_NODE* parentnode;
13909  currentnode = SCIPgetFocusNode(set->scip);
13910  parentnode = SCIPnodeGetParent(currentnode);
13911 
13912  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13913  f = fopen(filename, "a");
13914  if( NULL != f )
13915  {
13916  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13917  ++counter,
13918  SCIPvarGetName(var),
13919  SCIPnodeGetNumber(currentnode),
13920  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13921  SCIPgetNLPIterations(set->scip),
13922  SCIPgetDepth(set->scip),
13923  objdelta,
13924  solvaldelta);
13925  fclose(f);
13926  }
13927  }
13928 #endif
13929  return SCIP_OKAY;
13930 
13931  case SCIP_VARSTATUS_FIXED:
13932  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13933  return SCIP_INVALIDDATA;
13934 
13936  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13938  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13939  return SCIP_OKAY;
13940 
13942  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13943  return SCIP_INVALIDDATA;
13944 
13946  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13947  return SCIP_OKAY;
13948 
13949  default:
13950  SCIPerrorMessage("unknown variable status\n");
13951  return SCIP_INVALIDDATA;
13952  }
13953 }
13954 
13955 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13957  SCIP_VAR* var, /**< problem variable */
13958  SCIP_STAT* stat, /**< problem statistics */
13959  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13960  )
13961 {
13962  SCIP_BRANCHDIR dir;
13963 
13964  assert(var != NULL);
13965  assert(stat != NULL);
13966 
13967  switch( SCIPvarGetStatus(var) )
13968  {
13970  if( var->data.original.transvar == NULL )
13971  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13972  else
13973  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13974 
13975  case SCIP_VARSTATUS_LOOSE:
13976  case SCIP_VARSTATUS_COLUMN:
13977  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13978 
13979  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13980  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13981  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13982 
13983  case SCIP_VARSTATUS_FIXED:
13984  return 0.0;
13985 
13987  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13988 
13990  return 0.0;
13991 
13993  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13994 
13995  default:
13996  SCIPerrorMessage("unknown variable status\n");
13997  SCIPABORT();
13998  return 0.0; /*lint !e527*/
13999  }
14000 }
14001 
14002 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14003  * only using the pseudo cost information of the current run
14004  */
14006  SCIP_VAR* var, /**< problem variable */
14007  SCIP_STAT* stat, /**< problem statistics */
14008  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14009  )
14010 {
14011  SCIP_BRANCHDIR dir;
14012 
14013  assert(var != NULL);
14014  assert(stat != NULL);
14015 
14016  switch( SCIPvarGetStatus(var) )
14017  {
14019  if( var->data.original.transvar == NULL )
14020  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14021  else
14022  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14023 
14024  case SCIP_VARSTATUS_LOOSE:
14025  case SCIP_VARSTATUS_COLUMN:
14026  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14027 
14028  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14029  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14030  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14031 
14032  case SCIP_VARSTATUS_FIXED:
14033  return 0.0;
14034 
14036  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14037 
14039  return 0.0;
14040 
14042  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14043 
14044  default:
14045  SCIPerrorMessage("unknown variable status\n");
14046  SCIPABORT();
14047  return 0.0; /*lint !e527*/
14048  }
14049 }
14050 
14051 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14053  SCIP_VAR* var, /**< problem variable */
14054  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14055  )
14056 {
14057  assert(var != NULL);
14058  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14059 
14060  switch( SCIPvarGetStatus(var) )
14061  {
14063  if( var->data.original.transvar == NULL )
14064  return 0.0;
14065  else
14066  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14067 
14068  case SCIP_VARSTATUS_LOOSE:
14069  case SCIP_VARSTATUS_COLUMN:
14070  return SCIPhistoryGetPseudocostCount(var->history, dir);
14071 
14072  case SCIP_VARSTATUS_FIXED:
14073  return 0.0;
14074 
14076  if( var->data.aggregate.scalar > 0.0 )
14077  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14078  else
14080 
14082  return 0.0;
14083 
14086 
14087  default:
14088  SCIPerrorMessage("unknown variable status\n");
14089  SCIPABORT();
14090  return 0.0; /*lint !e527*/
14091  }
14092 }
14093 
14094 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14095  * only using the pseudo cost information of the current run
14096  */
14098  SCIP_VAR* var, /**< problem variable */
14099  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14100  )
14101 {
14102  assert(var != NULL);
14103  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14104 
14105  switch( SCIPvarGetStatus(var) )
14106  {
14108  if( var->data.original.transvar == NULL )
14109  return 0.0;
14110  else
14112 
14113  case SCIP_VARSTATUS_LOOSE:
14114  case SCIP_VARSTATUS_COLUMN:
14115  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14116 
14117  case SCIP_VARSTATUS_FIXED:
14118  return 0.0;
14119 
14121  if( var->data.aggregate.scalar > 0.0 )
14123  else
14125 
14127  return 0.0;
14128 
14131 
14132  default:
14133  SCIPerrorMessage("unknown variable status\n");
14134  SCIPABORT();
14135  return 0.0; /*lint !e527*/
14136  }
14137 }
14138 
14139 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14141  SCIP_VAR* var, /**< problem variable */
14142  SCIP_STAT* stat, /**< problem statistics */
14143  SCIP_SET* set, /**< global SCIP settings */
14144  SCIP_Real solval /**< solution value, e.g., LP solution value */
14145  )
14146 {
14147  SCIP_Real upscore;
14148  SCIP_Real downscore;
14149  SCIP_Real solvaldeltaup;
14150  SCIP_Real solvaldeltadown;
14151 
14152  /* LP root estimate only works for variables with fractional LP root solution */
14153  if( SCIPsetIsFeasIntegral(set, solval) )
14154  return 0.0;
14155 
14156  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14158  return 0.0;
14159 
14160  /* compute delta's to ceil and floor of root LP solution value */
14161  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14162  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14163 
14164  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14165  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14166 
14167  return MIN(upscore, downscore);
14168 }
14169 
14170 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14172  SCIP_VAR* var, /**< problem variable */
14173  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14174  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14175  )
14176 {
14177  assert(var != NULL);
14178  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14179 
14180  switch( SCIPvarGetStatus(var) )
14181  {
14183  if( var->data.original.transvar == NULL )
14184  return 0.0;
14185  else
14186  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14187 
14188  case SCIP_VARSTATUS_LOOSE:
14189  case SCIP_VARSTATUS_COLUMN:
14190  if( onlycurrentrun )
14192  else
14193  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14194 
14195  case SCIP_VARSTATUS_FIXED:
14196  return 0.0;
14197 
14199  if( var->data.aggregate.scalar > 0.0 )
14200  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14201  else
14202  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14203 
14205  return 0.0;
14206 
14208  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14209 
14210  default:
14211  SCIPerrorMessage("unknown variable status\n");
14212  SCIPABORT();
14213  return 0.0; /*lint !e527*/
14214  }
14215 }
14216 
14217 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14218  *
14219  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14220  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14221  * of 2 * clevel - 1.
14222  *
14223  * @return value of confidence bound for this variable
14224  */
14226  SCIP_VAR* var, /**< variable in question */
14227  SCIP_SET* set, /**< global SCIP settings */
14228  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14229  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14230  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14231  )
14232 {
14233  SCIP_Real confidencebound;
14234 
14235  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14236  if( SCIPsetIsFeasPositive(set, confidencebound) )
14237  {
14238  SCIP_Real count;
14239 
14240  if( onlycurrentrun )
14241  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14242  else
14243  count = SCIPvarGetPseudocostCount(var, dir);
14244  /* assertion is valid because variance is positive */
14245  assert(count >= 1.9);
14246 
14247  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14248  confidencebound = sqrt(confidencebound);
14249 
14250  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14251  * the number of pseudo cost evaluations of this variable in the respective direction. */
14252  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14253  }
14254  else
14255  confidencebound = 0.0;
14256 
14257  return confidencebound;
14258 }
14259 
14260 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14261  * Error is calculated at a specific confidence level
14262  */
14264  SCIP_VAR* var, /**< variable in question */
14265  SCIP_SET* set, /**< global SCIP settings */
14266  SCIP_STAT* stat, /**< problem statistics */
14267  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14268  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14269  )
14270 {
14271  SCIP_Real downsize;
14272  SCIP_Real upsize;
14273  SCIP_Real size;
14274  SCIP_Real relerrorup;
14275  SCIP_Real relerrordown;
14276  SCIP_Real relerror;
14277 
14278  /* check, if the pseudo cost score of the variable is reliable */
14281  size = MIN(downsize, upsize);
14282 
14283  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14284  if( size <= 1.9 )
14285  return FALSE;
14286 
14287  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14288  * confidence interval bound at confidence level of 95% for individual variable reliability.
14289  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14290  */
14291  if( downsize >= 1.9 )
14292  {
14293  SCIP_Real normval;
14294 
14295  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14296  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14297  normval = MAX(1.0, normval);
14298 
14299  relerrordown /= normval;
14300  }
14301  else
14302  relerrordown = 0.0;
14303 
14304  if( upsize >= 1.9 )
14305  {
14306  SCIP_Real normval;
14307 
14308  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14309  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14310  normval = MAX(1.0, normval);
14311  relerrorup /= normval;
14312  }
14313  else
14314  relerrorup = 0.0;
14315 
14316  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14317  relerror = MAX(relerrorup, relerrordown);
14318 
14319  return (relerror <= threshold);
14320 }
14321 
14322 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14323  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14324  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14325  * unknown location means of the underlying pseudo-cost distributions of x and y.
14326  *
14327  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14328  * better than x (despite the current information), meaning that y can be expected to yield branching
14329  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14330  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14331  * than y.
14332  *
14333  * @note The order of x and y matters for the one-sided hypothesis
14334  *
14335  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14336  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14337  *
14338  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14339  */
14341  SCIP_SET* set, /**< global SCIP settings */
14342  SCIP_STAT* stat, /**< problem statistics */
14343  SCIP_VAR* varx, /**< variable x */
14344  SCIP_Real fracx, /**< the fractionality of variable x */
14345  SCIP_VAR* vary, /**< variable y */
14346  SCIP_Real fracy, /**< the fractionality of variable y */
14347  SCIP_BRANCHDIR dir, /**< branching direction */
14348  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14349  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14350  )
14351 {
14352  SCIP_Real meanx;
14353  SCIP_Real meany;
14354  SCIP_Real variancex;
14355  SCIP_Real variancey;
14356  SCIP_Real countx;
14357  SCIP_Real county;
14358  SCIP_Real tresult;
14359  SCIP_Real realdirection;
14360 
14361  if( varx == vary )
14362  return FALSE;
14363 
14364  countx = SCIPvarGetPseudocostCount(varx, dir);
14365  county = SCIPvarGetPseudocostCount(vary, dir);
14366 
14367  /* if not at least 2 measurements were taken, return FALSE */
14368  if( countx <= 1.9 || county <= 1.9 )
14369  return FALSE;
14370 
14371  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14372 
14373  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14374  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14375 
14376  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14377  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14378 
14379  /* if there is no variance, the means are taken from a constant distribution */
14380  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14381  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14382 
14383  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14384 
14385  /* for the two-sided hypothesis, just take the absolute of t */
14386  if( !onesided )
14387  tresult = REALABS(tresult);
14388 
14389  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14390 }
14391 
14392 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14393  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14394  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14395  * of at least \p threshold.
14396  *
14397  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14398  * the estimated probability to exceed \p threshold is less than 25 %.
14399  *
14400  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14401  * of confidence.
14402  *
14403  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14404  * at the given confidence level \p clevel.
14405  */
14407  SCIP_SET* set, /**< global SCIP settings */
14408  SCIP_STAT* stat, /**< problem statistics */
14409  SCIP_VAR* var, /**< variable x */
14410  SCIP_Real frac, /**< the fractionality of variable x */
14411  SCIP_Real threshold, /**< the threshold to test against */
14412  SCIP_BRANCHDIR dir, /**< branching direction */
14413  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14414  )
14415 {
14416  SCIP_Real mean;
14417  SCIP_Real variance;
14418  SCIP_Real count;
14419  SCIP_Real realdirection;
14420  SCIP_Real probability;
14421  SCIP_Real problimit;
14422 
14423  count = SCIPvarGetPseudocostCount(var, dir);
14424 
14425  /* if not at least 2 measurements were taken, return FALSE */
14426  if( count <= 1.9 )
14427  return FALSE;
14428 
14429  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14430 
14431  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14432  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14433 
14434  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14435  if( SCIPsetIsFeasGE(set, mean, threshold) )
14436  return FALSE;
14437 
14438  /* if there is no variance, the means are taken from a constant distribution */
14439  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14440  return SCIPsetIsFeasLT(set, mean, threshold);
14441 
14442  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14443  probability = SCIPnormalCDF(mean, variance, threshold);
14444 
14445  /* determine a probability limit corresponding to the given confidence level */
14446  switch( clevel )
14447  {
14449  problimit = 0.75;
14450  break;
14452  problimit = 0.875;
14453  break;
14455  problimit = 0.9;
14456  break;
14458  problimit = 0.95;
14459  break;
14461  problimit = 0.975;
14462  break;
14463  default:
14464  problimit = -1;
14465  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14466  SCIPABORT();
14467  break;
14468  }
14469 
14470  return (probability >= problimit);
14471 }
14472 
14473 /** find the corresponding history entry if already existing, otherwise create new entry */
14474 static
14476  SCIP_VAR* var, /**< problem variable */
14477  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14478  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14479  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14480  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14481  )
14482 {
14483  assert(var != NULL);
14484  assert(blkmem != NULL);
14485  assert(set != NULL);
14486  assert(history != NULL);
14487 
14488  (*history) = NULL;
14489 
14490  if( var->valuehistory == NULL )
14491  {
14492  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14493  }
14494 
14495  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14496 
14497  return SCIP_OKAY;
14498 }
14499 
14500 /** check if value based history should be used */
14501 static
14503  SCIP_VAR* var, /**< problem variable */
14504  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14505  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14506  )
14507 {
14508  /* check if the domain value is unknown (not specific) */
14509  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14510  return FALSE;
14511 
14512  assert(set != NULL);
14513 
14514  /* check if value based history should be collected */
14515  if( !set->history_valuebased )
14516  return FALSE;
14517 
14518  /* value based history is not collected for binary variable since the standard history already contains all information */
14519  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14520  return FALSE;
14521 
14522  /* value based history is not collected for continuous variables */
14524  return FALSE;
14525 
14526  return TRUE;
14527 }
14528 
14529 /** increases VSIDS of the variable by the given weight */
14531  SCIP_VAR* var, /**< problem variable */
14532  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14533  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14534  SCIP_STAT* stat, /**< problem statistics */
14535  SCIP_BRANCHDIR dir, /**< branching direction */
14536  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14537  SCIP_Real weight /**< weight of this update in VSIDS */
14538  )
14539 {
14540  assert(var != NULL);
14541  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14542 
14543  /* check if history statistics should be collected for a variable */
14544  if( !stat->collectvarhistory )
14545  return SCIP_OKAY;
14546 
14547  if( SCIPsetIsZero(set, weight) )
14548  return SCIP_OKAY;
14549 
14550  switch( SCIPvarGetStatus(var) )
14551  {
14553  if( var->data.original.transvar == NULL )
14554  {
14555  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14556  return SCIP_INVALIDDATA;
14557  }
14558  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14559  return SCIP_OKAY;
14560 
14561  case SCIP_VARSTATUS_LOOSE:
14562  case SCIP_VARSTATUS_COLUMN:
14563  {
14564  SCIPhistoryIncVSIDS(var->history, dir, weight);
14565  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14566 
14567  if( useValuehistory(var, value, set) )
14568  {
14569  SCIP_HISTORY* history;
14570 
14571  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14572  assert(history != NULL);
14573 
14574  SCIPhistoryIncVSIDS(history, dir, weight);
14575  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14576  value, weight, SCIPhistoryGetVSIDS(history, dir));
14577  }
14578 
14579  return SCIP_OKAY;
14580  }
14581  case SCIP_VARSTATUS_FIXED:
14582  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14583  return SCIP_INVALIDDATA;
14584 
14586  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14587 
14588  if( var->data.aggregate.scalar > 0.0 )
14589  {
14590  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14591  }
14592  else
14593  {
14594  assert(var->data.aggregate.scalar < 0.0);
14595  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14596  }
14597  return SCIP_OKAY;
14598 
14600  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14601  return SCIP_INVALIDDATA;
14602 
14604  value = 1.0 - value;
14605 
14606  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14607  return SCIP_OKAY;
14608 
14609  default:
14610  SCIPerrorMessage("unknown variable status\n");
14611  return SCIP_INVALIDDATA;
14612  }
14613 }
14614 
14615 /** scales the VSIDS of the variable by the given scalar */
14617  SCIP_VAR* var, /**< problem variable */
14618  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14619  )
14620 {
14621  assert(var != NULL);
14622 
14623  switch( SCIPvarGetStatus(var) )
14624  {
14626  if( var->data.original.transvar == NULL )
14627  {
14628  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14629  return SCIP_INVALIDDATA;
14630  }
14632  return SCIP_OKAY;
14633 
14634  case SCIP_VARSTATUS_LOOSE:
14635  case SCIP_VARSTATUS_COLUMN:
14636  {
14637  SCIPhistoryScaleVSIDS(var->history, scalar);
14638  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14640 
14641  return SCIP_OKAY;
14642  }
14643  case SCIP_VARSTATUS_FIXED:
14644  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14645  return SCIP_INVALIDDATA;
14646 
14648  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14649  return SCIP_OKAY;
14650 
14652  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14653  return SCIP_INVALIDDATA;
14654 
14656  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14657  return SCIP_OKAY;
14658 
14659  default:
14660  SCIPerrorMessage("unknown variable status\n");
14661  return SCIP_INVALIDDATA;
14662  }
14663 }
14664 
14665 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14667  SCIP_VAR* var, /**< problem variable */
14668  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14669  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14670  SCIP_STAT* stat, /**< problem statistics */
14671  SCIP_BRANCHDIR dir, /**< branching direction */
14672  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14673  SCIP_Real length /**< length of the conflict */
14674  )
14675 {
14676  assert(var != NULL);
14677  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14678 
14679  /* check if history statistics should be collected for a variable */
14680  if( !stat->collectvarhistory )
14681  return SCIP_OKAY;
14682 
14683  switch( SCIPvarGetStatus(var) )
14684  {
14686  if( var->data.original.transvar == NULL )
14687  {
14688  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14689  return SCIP_INVALIDDATA;
14690  }
14691  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14692  return SCIP_OKAY;
14693 
14694  case SCIP_VARSTATUS_LOOSE:
14695  case SCIP_VARSTATUS_COLUMN:
14696  {
14697  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14698  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14699 
14700  if( useValuehistory(var, value, set) )
14701  {
14702  SCIP_HISTORY* history;
14703 
14704  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14705  assert(history != NULL);
14706 
14707  SCIPhistoryIncNActiveConflicts(history, dir, length);
14708  }
14709 
14710  return SCIP_OKAY;
14711  }
14712  case SCIP_VARSTATUS_FIXED:
14713  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14714  return SCIP_INVALIDDATA;
14715 
14717  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14718 
14719  if( var->data.aggregate.scalar > 0.0 )
14720  {
14721  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14722  }
14723  else
14724  {
14725  assert(var->data.aggregate.scalar < 0.0);
14726  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14727  }
14728  return SCIP_OKAY;
14729 
14731  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14732  return SCIP_INVALIDDATA;
14733 
14735  value = 1.0 - value;
14736 
14737  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14738  return SCIP_OKAY;
14739 
14740  default:
14741  SCIPerrorMessage("unknown variable status\n");
14742  return SCIP_INVALIDDATA;
14743  }
14744 }
14745 
14746 /** gets the number of active conflicts containing this variable in given direction */
14748  SCIP_VAR* var, /**< problem variable */
14749  SCIP_STAT* stat, /**< problem statistics */
14750  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14751  )
14752 {
14753  assert(var != NULL);
14754  assert(stat != NULL);
14755  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14756 
14757  switch( SCIPvarGetStatus(var) )
14758  {
14760  if( var->data.original.transvar == NULL )
14761  return 0;
14762  else
14763  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14764 
14765  case SCIP_VARSTATUS_LOOSE:
14766  case SCIP_VARSTATUS_COLUMN:
14767  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14768 
14769  case SCIP_VARSTATUS_FIXED:
14770  return 0;
14771 
14773  if( var->data.aggregate.scalar > 0.0 )
14774  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14775  else
14777 
14779  return 0;
14780 
14783 
14784  default:
14785  SCIPerrorMessage("unknown variable status\n");
14786  SCIPABORT();
14787  return 0; /*lint !e527*/
14788  }
14789 }
14790 
14791 /** gets the number of active conflicts containing this variable in given direction
14792  * in the current run
14793  */
14795  SCIP_VAR* var, /**< problem variable */
14796  SCIP_STAT* stat, /**< problem statistics */
14797  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14798  )
14799 {
14800  assert(var != NULL);
14801  assert(stat != NULL);
14802  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14803 
14804  switch( SCIPvarGetStatus(var) )
14805  {
14807  if( var->data.original.transvar == NULL )
14808  return 0;
14809  else
14811 
14812  case SCIP_VARSTATUS_LOOSE:
14813  case SCIP_VARSTATUS_COLUMN:
14814  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14815 
14816  case SCIP_VARSTATUS_FIXED:
14817  return 0;
14818 
14820  if( var->data.aggregate.scalar > 0.0 )
14821  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14822  else
14824 
14826  return 0;
14827 
14830 
14831  default:
14832  SCIPerrorMessage("unknown variable status\n");
14833  SCIPABORT();
14834  return 0; /*lint !e527*/
14835  }
14836 }
14837 
14838 /** gets the average conflict length in given direction due to branching on the variable */
14840  SCIP_VAR* var, /**< problem variable */
14841  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14842  )
14843 {
14844  assert(var != NULL);
14845  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14846 
14847  switch( SCIPvarGetStatus(var) )
14848  {
14850  if( var->data.original.transvar == NULL )
14851  return 0.0;
14852  else
14854 
14855  case SCIP_VARSTATUS_LOOSE:
14856  case SCIP_VARSTATUS_COLUMN:
14857  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14858  case SCIP_VARSTATUS_FIXED:
14859  return 0.0;
14860 
14862  if( var->data.aggregate.scalar > 0.0 )
14863  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14864  else
14866 
14868  return 0.0;
14869 
14872 
14873  default:
14874  SCIPerrorMessage("unknown variable status\n");
14875  SCIPABORT();
14876  return 0.0; /*lint !e527*/
14877  }
14878 }
14879 
14880 /** gets the average conflict length in given direction due to branching on the variable
14881  * in the current run
14882  */
14884  SCIP_VAR* var, /**< problem variable */
14885  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14886  )
14887 {
14888  assert(var != NULL);
14889  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14890 
14891  switch( SCIPvarGetStatus(var) )
14892  {
14894  if( var->data.original.transvar == NULL )
14895  return 0.0;
14896  else
14898 
14899  case SCIP_VARSTATUS_LOOSE:
14900  case SCIP_VARSTATUS_COLUMN:
14901  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14902 
14903  case SCIP_VARSTATUS_FIXED:
14904  return 0.0;
14905 
14907  if( var->data.aggregate.scalar > 0.0 )
14909  else
14911 
14913  return 0.0;
14914 
14917 
14918  default:
14919  SCIPerrorMessage("unknown variable status\n");
14920  SCIPABORT();
14921  return 0.0; /*lint !e527*/
14922  }
14923 }
14924 
14925 /** increases the number of branchings counter of the variable */
14927  SCIP_VAR* var, /**< problem variable */
14928  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14929  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14930  SCIP_STAT* stat, /**< problem statistics */
14931  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14932  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14933  int depth /**< depth at which the bound change took place */
14934  )
14935 {
14936  assert(var != NULL);
14937  assert(stat != NULL);
14938  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14939 
14940  /* check if history statistics should be collected for a variable */
14941  if( !stat->collectvarhistory )
14942  return SCIP_OKAY;
14943 
14944  switch( SCIPvarGetStatus(var) )
14945  {
14947  if( var->data.original.transvar == NULL )
14948  {
14949  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14950  return SCIP_INVALIDDATA;
14951  }
14952  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14953  return SCIP_OKAY;
14954 
14955  case SCIP_VARSTATUS_LOOSE:
14956  case SCIP_VARSTATUS_COLUMN:
14957  {
14958  SCIPhistoryIncNBranchings(var->history, dir, depth);
14959  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14960  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14961  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14962 
14963  if( useValuehistory(var, value, set) )
14964  {
14965  SCIP_HISTORY* history;
14966 
14967  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14968  assert(history != NULL);
14969 
14970  SCIPhistoryIncNBranchings(history, dir, depth);
14971  }
14972 
14973  return SCIP_OKAY;
14974  }
14975  case SCIP_VARSTATUS_FIXED:
14976  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14977  return SCIP_INVALIDDATA;
14978 
14980  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14981 
14982  if( var->data.aggregate.scalar > 0.0 )
14983  {
14984  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14985  }
14986  else
14987  {
14988  assert(var->data.aggregate.scalar < 0.0);
14989  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14990  }
14991  return SCIP_OKAY;
14992 
14994  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14995  return SCIP_INVALIDDATA;
14996 
14998  value = 1.0 - value;
14999 
15000  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15001  return SCIP_OKAY;
15002 
15003  default:
15004  SCIPerrorMessage("unknown variable status\n");
15005  return SCIP_INVALIDDATA;
15006  }
15007 }
15008 
15009 /** increases the inference sum of the variable by the given weight */
15011  SCIP_VAR* var, /**< problem variable */
15012  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15013  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15014  SCIP_STAT* stat, /**< problem statistics */
15015  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15016  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15017  SCIP_Real weight /**< weight of this update in inference score */
15018  )
15019 {
15020  assert(var != NULL);
15021  assert(stat != NULL);
15022  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15023 
15024  /* check if history statistics should be collected for a variable */
15025  if( !stat->collectvarhistory )
15026  return SCIP_OKAY;
15027 
15028  switch( SCIPvarGetStatus(var) )
15029  {
15031  if( var->data.original.transvar == NULL )
15032  {
15033  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15034  return SCIP_INVALIDDATA;
15035  }
15036  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15037  return SCIP_OKAY;
15038 
15039  case SCIP_VARSTATUS_LOOSE:
15040  case SCIP_VARSTATUS_COLUMN:
15041  {
15042  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15043  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15044  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15045  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15046 
15047  if( useValuehistory(var, value, set) )
15048  {
15049  SCIP_HISTORY* history;
15050 
15051  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15052  assert(history != NULL);
15053 
15054  SCIPhistoryIncInferenceSum(history, dir, weight);
15055  }
15056 
15057  return SCIP_OKAY;
15058  }
15059  case SCIP_VARSTATUS_FIXED:
15060  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15061  return SCIP_INVALIDDATA;
15062 
15064  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15065 
15066  if( var->data.aggregate.scalar > 0.0 )
15067  {
15068  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15069  }
15070  else
15071  {
15072  assert(var->data.aggregate.scalar < 0.0);
15073  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15074  }
15075  return SCIP_OKAY;
15076 
15078  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15079  return SCIP_INVALIDDATA;
15080 
15082  value = 1.0 - value;
15083 
15084  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15085  return SCIP_OKAY;
15086 
15087  default:
15088  SCIPerrorMessage("unknown variable status\n");
15089  return SCIP_INVALIDDATA;
15090  }
15091 }
15092 
15093 /** increases the cutoff sum of the variable by the given weight */
15095  SCIP_VAR* var, /**< problem variable */
15096  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15097  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15098  SCIP_STAT* stat, /**< problem statistics */
15099  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15100  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15101  SCIP_Real weight /**< weight of this update in cutoff score */
15102  )
15103 {
15104  assert(var != NULL);
15105  assert(stat != NULL);
15106  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15107 
15108  /* check if history statistics should be collected for a variable */
15109  if( !stat->collectvarhistory )
15110  return SCIP_OKAY;
15111 
15112  switch( SCIPvarGetStatus(var) )
15113  {
15115  if( var->data.original.transvar == NULL )
15116  {
15117  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15118  return SCIP_INVALIDDATA;
15119  }
15120  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15121  return SCIP_OKAY;
15122 
15123  case SCIP_VARSTATUS_LOOSE:
15124  case SCIP_VARSTATUS_COLUMN:
15125  {
15126  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15127  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15128  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15129  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15130 
15131  if( useValuehistory(var, value, set) )
15132  {
15133  SCIP_HISTORY* history;
15134 
15135  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15136  assert(history != NULL);
15137 
15138  SCIPhistoryIncCutoffSum(history, dir, weight);
15139  }
15140 
15141  return SCIP_OKAY;
15142  }
15143  case SCIP_VARSTATUS_FIXED:
15144  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15145  return SCIP_INVALIDDATA;
15146 
15148  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15149 
15150  if( var->data.aggregate.scalar > 0.0 )
15151  {
15152  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15153  }
15154  else
15155  {
15156  assert(var->data.aggregate.scalar < 0.0);
15157  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15158  }
15159  return SCIP_OKAY;
15160 
15162  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15163  return SCIP_INVALIDDATA;
15164 
15166  value = 1.0 - value;
15167 
15168  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15169  return SCIP_OKAY;
15170 
15171  default:
15172  SCIPerrorMessage("unknown variable status\n");
15173  return SCIP_INVALIDDATA;
15174  }
15175 }
15176 
15177 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15179  SCIP_VAR* var, /**< problem variable */
15180  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15181  )
15182 {
15183  assert(var != NULL);
15184  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15185 
15186  switch( SCIPvarGetStatus(var) )
15187  {
15189  if( var->data.original.transvar == NULL )
15190  return 0;
15191  else
15192  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15193 
15194  case SCIP_VARSTATUS_LOOSE:
15195  case SCIP_VARSTATUS_COLUMN:
15196  return SCIPhistoryGetNBranchings(var->history, dir);
15197 
15198  case SCIP_VARSTATUS_FIXED:
15199  return 0;
15200 
15202  if( var->data.aggregate.scalar > 0.0 )
15203  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15204  else
15206 
15208  return 0;
15209 
15212 
15213  default:
15214  SCIPerrorMessage("unknown variable status\n");
15215  SCIPABORT();
15216  return 0; /*lint !e527*/
15217  }
15218 }
15219 
15220 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15221  * in the current run
15222  */
15224  SCIP_VAR* var, /**< problem variable */
15225  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15226  )
15227 {
15228  assert(var != NULL);
15229  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15230 
15231  switch( SCIPvarGetStatus(var) )
15232  {
15234  if( var->data.original.transvar == NULL )
15235  return 0;
15236  else
15238 
15239  case SCIP_VARSTATUS_LOOSE:
15240  case SCIP_VARSTATUS_COLUMN:
15241  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15242 
15243  case SCIP_VARSTATUS_FIXED:
15244  return 0;
15245 
15247  if( var->data.aggregate.scalar > 0.0 )
15249  else
15251 
15253  return 0;
15254 
15257 
15258  default:
15259  SCIPerrorMessage("unknown variable status\n");
15260  SCIPABORT();
15261  return 0; /*lint !e527*/
15262  }
15263 }
15264 
15265 /** returns the average depth of bound changes in given direction due to branching on the variable */
15267  SCIP_VAR* var, /**< problem variable */
15268  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15269  )
15270 {
15271  assert(var != NULL);
15272  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15273 
15274  switch( SCIPvarGetStatus(var) )
15275  {
15277  if( var->data.original.transvar == NULL )
15278  return 0.0;
15279  else
15280  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15281 
15282  case SCIP_VARSTATUS_LOOSE:
15283  case SCIP_VARSTATUS_COLUMN:
15284  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15285 
15286  case SCIP_VARSTATUS_FIXED:
15287  return 0.0;
15288 
15290  if( var->data.aggregate.scalar > 0.0 )
15291  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15292  else
15294 
15296  return 0.0;
15297 
15300 
15301  default:
15302  SCIPerrorMessage("unknown variable status\n");
15303  SCIPABORT();
15304  return 0.0; /*lint !e527*/
15305  }
15306 }
15307 
15308 /** returns the average depth of bound changes in given direction due to branching on the variable
15309  * in the current run
15310  */
15312  SCIP_VAR* var, /**< problem variable */
15313  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15314  )
15315 {
15316  assert(var != NULL);
15317  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15318 
15319  switch( SCIPvarGetStatus(var) )
15320  {
15322  if( var->data.original.transvar == NULL )
15323  return 0.0;
15324  else
15326 
15327  case SCIP_VARSTATUS_LOOSE:
15328  case SCIP_VARSTATUS_COLUMN:
15329  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15330 
15331  case SCIP_VARSTATUS_FIXED:
15332  return 0.0;
15333 
15335  if( var->data.aggregate.scalar > 0.0 )
15337  else
15340 
15342  return 0.0;
15343 
15346  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15347 
15348  default:
15349  SCIPerrorMessage("unknown variable status\n");
15350  SCIPABORT();
15351  return 0.0; /*lint !e527*/
15352  }
15353 }
15354 
15355 /** returns the variable's VSIDS score */
15357  SCIP_VAR* var, /**< problem variable */
15358  SCIP_STAT* stat, /**< problem statistics */
15359  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15360  )
15361 {
15362  assert(var != NULL);
15363  assert(stat != NULL);
15364  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15365 
15367  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15368 
15369  switch( SCIPvarGetStatus(var) )
15370  {
15372  if( var->data.original.transvar == NULL )
15373  return 0.0;
15374  else
15375  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15376 
15377  case SCIP_VARSTATUS_LOOSE:
15378  case SCIP_VARSTATUS_COLUMN:
15379  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15380  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15381 
15382  case SCIP_VARSTATUS_FIXED:
15383  return 0.0;
15384 
15386  if( var->data.aggregate.scalar > 0.0 )
15387  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15388  else
15389  /* coverity[overrun-local] */
15390  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15391 
15393  return 0.0;
15394 
15396  /* coverity[overrun-local] */
15397  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15398 
15399  default:
15400  SCIPerrorMessage("unknown variable status\n");
15401  SCIPABORT();
15402  return 0.0; /*lint !e527*/
15403  }
15404 }
15405 
15406 /** returns the variable's VSIDS score only using conflicts of the current run */
15408  SCIP_VAR* var, /**< problem variable */
15409  SCIP_STAT* stat, /**< problem statistics */
15410  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15411  )
15412 {
15413  assert(var != NULL);
15414  assert(stat != NULL);
15415  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15416 
15417  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15418  {
15419  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15420  return SCIP_INVALID;
15421  }
15422 
15423  switch( SCIPvarGetStatus(var) )
15424  {
15426  if( var->data.original.transvar == NULL )
15427  return 0.0;
15428  else
15429  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15430 
15431  case SCIP_VARSTATUS_LOOSE:
15432  case SCIP_VARSTATUS_COLUMN:
15433  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15434 
15435  case SCIP_VARSTATUS_FIXED:
15436  return 0.0;
15437 
15439  if( var->data.aggregate.scalar > 0.0 )
15440  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15441  else
15443 
15445  return 0.0;
15446 
15449 
15450  default:
15451  SCIPerrorMessage("unknown variable status\n");
15452  SCIPABORT();
15453  return 0.0; /*lint !e527*/
15454  }
15455 }
15456 
15457 /** returns the number of inferences branching on this variable in given direction triggered */
15459  SCIP_VAR* var, /**< problem variable */
15460  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15461  )
15462 {
15463  assert(var != NULL);
15464  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15465 
15466  switch( SCIPvarGetStatus(var) )
15467  {
15469  if( var->data.original.transvar == NULL )
15470  return 0.0;
15471  else
15472  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15473 
15474  case SCIP_VARSTATUS_LOOSE:
15475  case SCIP_VARSTATUS_COLUMN:
15476  return SCIPhistoryGetInferenceSum(var->history, dir);
15477 
15478  case SCIP_VARSTATUS_FIXED:
15479  return 0.0;
15480 
15482  if( var->data.aggregate.scalar > 0.0 )
15483  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15484  else
15486 
15488  return 0.0;
15489 
15492 
15493  default:
15494  SCIPerrorMessage("unknown variable status\n");
15495  SCIPABORT();
15496  return 0.0; /*lint !e527*/
15497  }
15498 }
15499 
15500 /** returns the number of inferences branching on this variable in given direction triggered
15501  * in the current run
15502  */
15504  SCIP_VAR* var, /**< problem variable */
15505  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15506  )
15507 {
15508  assert(var != NULL);
15509  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15510 
15511  switch( SCIPvarGetStatus(var) )
15512  {
15514  if( var->data.original.transvar == NULL )
15515  return 0.0;
15516  else
15518 
15519  case SCIP_VARSTATUS_LOOSE:
15520  case SCIP_VARSTATUS_COLUMN:
15521  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15522 
15523  case SCIP_VARSTATUS_FIXED:
15524  return 0.0;
15525 
15527  if( var->data.aggregate.scalar > 0.0 )
15529  else
15531 
15533  return 0.0;
15534 
15537 
15538  default:
15539  SCIPerrorMessage("unknown variable status\n");
15540  SCIPABORT();
15541  return 0.0; /*lint !e527*/
15542  }
15543 }
15544 
15545 /** returns the average number of inferences found after branching on the variable in given direction */
15547  SCIP_VAR* var, /**< problem variable */
15548  SCIP_STAT* stat, /**< problem statistics */
15549  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15550  )
15551 {
15552  assert(var != NULL);
15553  assert(stat != NULL);
15554  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15555 
15556  switch( SCIPvarGetStatus(var) )
15557  {
15559  if( var->data.original.transvar == NULL )
15560  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15561  else
15562  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15563 
15564  case SCIP_VARSTATUS_LOOSE:
15565  case SCIP_VARSTATUS_COLUMN:
15566  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15567  return SCIPhistoryGetAvgInferences(var->history, dir);
15568  else
15569  {
15570  int nimpls;
15571  int ncliques;
15572 
15573  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15574  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15575  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15576  }
15577 
15578  case SCIP_VARSTATUS_FIXED:
15579  return 0.0;
15580 
15582  if( var->data.aggregate.scalar > 0.0 )
15583  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15584  else
15586 
15588  return 0.0;
15589 
15591  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15592 
15593  default:
15594  SCIPerrorMessage("unknown variable status\n");
15595  SCIPABORT();
15596  return 0.0; /*lint !e527*/
15597  }
15598 }
15599 
15600 /** returns the average number of inferences found after branching on the variable in given direction
15601  * in the current run
15602  */
15604  SCIP_VAR* var, /**< problem variable */
15605  SCIP_STAT* stat, /**< problem statistics */
15606  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15607  )
15608 {
15609  assert(var != NULL);
15610  assert(stat != NULL);
15611  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15612 
15613  switch( SCIPvarGetStatus(var) )
15614  {
15616  if( var->data.original.transvar == NULL )
15617  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15618  else
15619  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15620 
15621  case SCIP_VARSTATUS_LOOSE:
15622  case SCIP_VARSTATUS_COLUMN:
15623  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15624  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15625  else
15626  {
15627  int nimpls;
15628  int ncliques;
15629 
15630  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15631  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15632  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15633  }
15634 
15635  case SCIP_VARSTATUS_FIXED:
15636  return 0.0;
15637 
15639  if( var->data.aggregate.scalar > 0.0 )
15640  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15641  else
15643 
15645  return 0.0;
15646 
15649 
15650  default:
15651  SCIPerrorMessage("unknown variable status\n");
15652  SCIPABORT();
15653  return 0.0; /*lint !e527*/
15654  }
15655 }
15656 
15657 /** returns the number of cutoffs branching on this variable in given direction produced */
15659  SCIP_VAR* var, /**< problem variable */
15660  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15661  )
15662 {
15663  assert(var != NULL);
15664  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15665 
15666  switch( SCIPvarGetStatus(var) )
15667  {
15669  if( var->data.original.transvar == NULL )
15670  return 0;
15671  else
15672  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15673 
15674  case SCIP_VARSTATUS_LOOSE:
15675  case SCIP_VARSTATUS_COLUMN:
15676  return SCIPhistoryGetCutoffSum(var->history, dir);
15677 
15678  case SCIP_VARSTATUS_FIXED:
15679  return 0;
15680 
15682  if( var->data.aggregate.scalar > 0.0 )
15683  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15684  else
15686 
15688  return 0;
15689 
15692 
15693  default:
15694  SCIPerrorMessage("unknown variable status\n");
15695  SCIPABORT();
15696  return 0; /*lint !e527*/
15697  }
15698 }
15699 
15700 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15702  SCIP_VAR* var, /**< problem variable */
15703  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15704  )
15705 {
15706  assert(var != NULL);
15707  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15708 
15709  switch( SCIPvarGetStatus(var) )
15710  {
15712  if( var->data.original.transvar == NULL )
15713  return 0;
15714  else
15716 
15717  case SCIP_VARSTATUS_LOOSE:
15718  case SCIP_VARSTATUS_COLUMN:
15719  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15720 
15721  case SCIP_VARSTATUS_FIXED:
15722  return 0;
15723 
15725  if( var->data.aggregate.scalar > 0.0 )
15726  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15727  else
15729 
15731  return 0;
15732 
15735 
15736  default:
15737  SCIPerrorMessage("unknown variable status\n");
15738  SCIPABORT();
15739  return 0; /*lint !e527*/
15740  }
15741 }
15742 
15743 /** returns the average number of cutoffs found after branching on the variable in given direction */
15745  SCIP_VAR* var, /**< problem variable */
15746  SCIP_STAT* stat, /**< problem statistics */
15747  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15748  )
15749 {
15750  assert(var != NULL);
15751  assert(stat != NULL);
15752  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15753 
15754  switch( SCIPvarGetStatus(var) )
15755  {
15757  if( var->data.original.transvar == NULL )
15758  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15759  else
15760  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15761 
15762  case SCIP_VARSTATUS_LOOSE:
15763  case SCIP_VARSTATUS_COLUMN:
15764  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15765  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15766  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15767 
15768  case SCIP_VARSTATUS_FIXED:
15769  return 0.0;
15770 
15772  if( var->data.aggregate.scalar > 0.0 )
15773  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15774  else
15775  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15776 
15778  return 0.0;
15779 
15781  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15782 
15783  default:
15784  SCIPerrorMessage("unknown variable status\n");
15785  SCIPABORT();
15786  return 0.0; /*lint !e527*/
15787  }
15788 }
15789 
15790 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15792  SCIP_VAR* var, /**< problem variable */
15793  SCIP_STAT* stat, /**< problem statistics */
15794  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15795  )
15796 {
15797  assert(var != NULL);
15798  assert(stat != NULL);
15799  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15800 
15801  switch( SCIPvarGetStatus(var) )
15802  {
15804  if( var->data.original.transvar == NULL )
15805  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15806  else
15807  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15808 
15809  case SCIP_VARSTATUS_LOOSE:
15810  case SCIP_VARSTATUS_COLUMN:
15811  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15814 
15815  case SCIP_VARSTATUS_FIXED:
15816  return 0.0;
15817 
15819  if( var->data.aggregate.scalar > 0.0 )
15820  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15821  else
15823 
15825  return 0.0;
15826 
15829 
15830  default:
15831  SCIPerrorMessage("unknown variable status\n");
15832  SCIPABORT();
15833  return 0.0; /*lint !e527*/
15834  }
15835 }
15836 
15837 
15838 
15839 
15840 /*
15841  * information methods for bound changes
15842  */
15843 
15844 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15846  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15847  BMS_BLKMEM* blkmem, /**< block memory */
15848  SCIP_VAR* var, /**< active variable that changed the bounds */
15849  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15850  SCIP_Real oldbound, /**< old value for bound */
15851  SCIP_Real newbound /**< new value for bound */
15852  )
15853 {
15854  assert(bdchginfo != NULL);
15855 
15856  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15857  (*bdchginfo)->oldbound = oldbound;
15858  (*bdchginfo)->newbound = newbound;
15859  (*bdchginfo)->var = var;
15860  (*bdchginfo)->inferencedata.var = var;
15861  (*bdchginfo)->inferencedata.reason.prop = NULL;
15862  (*bdchginfo)->inferencedata.info = 0;
15863  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15864  (*bdchginfo)->bdchgidx.pos = -1;
15865  (*bdchginfo)->pos = 0;
15866  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15867  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15868  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15869  (*bdchginfo)->redundant = FALSE;
15870 
15871  return SCIP_OKAY;
15872 }
15873 
15874 /** frees a bound change information object */
15875 void SCIPbdchginfoFree(
15876  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15877  BMS_BLKMEM* blkmem /**< block memory */
15878  )
15879 {
15880  assert(bdchginfo != NULL);
15881 
15882  BMSfreeBlockMemory(blkmem, bdchginfo);
15883 }
15884 
15885 /** returns the bound change information for the last lower bound change on given active problem variable before or
15886  * after the bound change with the given index was applied;
15887  * returns NULL, if no change to the lower bound was applied up to this point of time
15888  */
15890  SCIP_VAR* var, /**< active problem variable */
15891  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15892  SCIP_Bool after /**< should the bound change with given index be included? */
15893  )
15894 {
15895  int i;
15896 
15897  assert(var != NULL);
15898  assert(SCIPvarIsActive(var));
15899 
15900  /* search the correct bound change information for the given bound change index */
15901  if( after )
15902  {
15903  for( i = var->nlbchginfos-1; i >= 0; --i )
15904  {
15905  assert(var->lbchginfos[i].var == var);
15907  assert(var->lbchginfos[i].pos == i);
15908 
15909  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15910  if( var->lbchginfos[i].redundant )
15911  return NULL;
15912  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15913 
15914  /* if we reached the bound change index, return the current bound change info */
15915  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15916  return &var->lbchginfos[i];
15917  }
15918  }
15919  else
15920  {
15921  for( i = var->nlbchginfos-1; i >= 0; --i )
15922  {
15923  assert(var->lbchginfos[i].var == var);
15925  assert(var->lbchginfos[i].pos == i);
15926 
15927  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15928  if( var->lbchginfos[i].redundant )
15929  return NULL;
15930  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15931 
15932  /* if we reached the bound change index, return the current bound change info */
15933  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15934  return &var->lbchginfos[i];
15935  }
15936  }
15937 
15938  return NULL;
15939 }
15940 
15941 /** returns the bound change information for the last upper bound change on given active problem variable before or
15942  * after the bound change with the given index was applied;
15943  * returns NULL, if no change to the upper bound was applied up to this point of time
15944  */
15946  SCIP_VAR* var, /**< active problem variable */
15947  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15948  SCIP_Bool after /**< should the bound change with given index be included? */
15949  )
15950 {
15951  int i;
15952 
15953  assert(var != NULL);
15954  assert(SCIPvarIsActive(var));
15955 
15956  /* search the correct bound change information for the given bound change index */
15957  if( after )
15958  {
15959  for( i = var->nubchginfos-1; i >= 0; --i )
15960  {
15961  assert(var->ubchginfos[i].var == var);
15963  assert(var->ubchginfos[i].pos == i);
15964 
15965  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15966  if( var->ubchginfos[i].redundant )
15967  return NULL;
15968  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15969 
15970  /* if we reached the bound change index, return the current bound change info */
15971  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15972  return &var->ubchginfos[i];
15973  }
15974  }
15975  else
15976  {
15977  for( i = var->nubchginfos-1; i >= 0; --i )
15978  {
15979  assert(var->ubchginfos[i].var == var);
15981  assert(var->ubchginfos[i].pos == i);
15982 
15983  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15984  if( var->ubchginfos[i].redundant )
15985  return NULL;
15986  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15987 
15988  /* if we reached the bound change index, return the current bound change info */
15989  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15990  return &var->ubchginfos[i];
15991  }
15992  }
15993 
15994  return NULL;
15995 }
15996 
15997 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15998  * before or after the bound change with the given index was applied;
15999  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16000  */
16002  SCIP_VAR* var, /**< active problem variable */
16003  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16004  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16005  SCIP_Bool after /**< should the bound change with given index be included? */
16006  )
16007 {
16008  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16009  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16010  else
16011  {
16012  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16013  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16014  }
16015 }
16016 
16017 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16018  * was applied
16019  *
16020  * @deprecated Please use SCIPgetVarLbAtIndex()
16021  */
16023  SCIP_VAR* var, /**< problem variable */
16024  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16025  SCIP_Bool after /**< should the bound change with given index be included? */
16026  )
16027 {
16028  SCIP_VARSTATUS varstatus;
16029  assert(var != NULL);
16030 
16031  varstatus = SCIPvarGetStatus(var);
16032 
16033  /* get bounds of attached variables */
16034  switch( varstatus )
16035  {
16037  assert(var->data.original.transvar != NULL);
16038  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16039 
16040  case SCIP_VARSTATUS_LOOSE:
16041  case SCIP_VARSTATUS_COLUMN:
16042  if( bdchgidx == NULL )
16043  return SCIPvarGetLbLocal(var);
16044  else
16045  {
16046  SCIP_BDCHGINFO* bdchginfo;
16047 
16048  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16049  if( bdchginfo != NULL )
16050  return SCIPbdchginfoGetNewbound(bdchginfo);
16051  else
16052  return var->glbdom.lb;
16053  }
16054  case SCIP_VARSTATUS_FIXED:
16055  return var->glbdom.lb;
16056 
16057  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16058  assert(var->data.aggregate.var != NULL);
16059  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16060  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16061  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16062  * (or is called by) a public interface method; instead, we only assert that values are finite
16063  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16064  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16065  */
16066  if( var->data.aggregate.scalar > 0.0 )
16067  {
16068  /* a > 0 -> get lower bound of y */
16069  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16070  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16071  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16072  + var->data.aggregate.constant;
16073  }
16074  else if( var->data.aggregate.scalar < 0.0 )
16075  {
16076  /* a < 0 -> get upper bound of y */
16077  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16078  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16079  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16080  + var->data.aggregate.constant;
16081  }
16082  else
16083  {
16084  SCIPerrorMessage("scalar is zero in aggregation\n");
16085  SCIPABORT();
16086  return SCIP_INVALID; /*lint !e527*/
16087  }
16088 
16090  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16091  if ( var->data.multaggr.nvars == 1 )
16092  {
16093  assert(var->data.multaggr.vars != NULL);
16094  assert(var->data.multaggr.scalars != NULL);
16095  assert(var->data.multaggr.vars[0] != NULL);
16096 
16097  if( var->data.multaggr.scalars[0] > 0.0 )
16098  {
16099  /* a > 0 -> get lower bound of y */
16100  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16101  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16102  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16103  + var->data.multaggr.constant;
16104  }
16105  else if( var->data.multaggr.scalars[0] < 0.0 )
16106  {
16107  /* a < 0 -> get upper bound of y */
16108  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16109  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16110  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16111  + var->data.multaggr.constant;
16112  }
16113  else
16114  {
16115  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16116  SCIPABORT();
16117  return SCIP_INVALID; /*lint !e527*/
16118  }
16119  }
16120  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16121  SCIPABORT();
16122  return SCIP_INVALID; /*lint !e527*/
16123 
16124  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16125  assert(var->negatedvar != NULL);
16127  assert(var->negatedvar->negatedvar == var);
16128  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16129  default:
16130  SCIPerrorMessage("unknown variable status\n");
16131  SCIPABORT();
16132  return SCIP_INVALID; /*lint !e527*/
16133  }
16134 }
16135 
16136 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16137  * was applied
16138  *
16139  * @deprecated Please use SCIPgetVarUbAtIndex()
16140  */
16142  SCIP_VAR* var, /**< problem variable */
16143  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16144  SCIP_Bool after /**< should the bound change with given index be included? */
16145  )
16146 {
16147  SCIP_VARSTATUS varstatus;
16148  assert(var != NULL);
16149 
16150  varstatus = SCIPvarGetStatus(var);
16151 
16152  /* get bounds of attached variables */
16153  switch( varstatus )
16154  {
16156  assert(var->data.original.transvar != NULL);
16157  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16158 
16159  case SCIP_VARSTATUS_COLUMN:
16160  case SCIP_VARSTATUS_LOOSE:
16161  if( bdchgidx == NULL )
16162  return SCIPvarGetUbLocal(var);
16163  else
16164  {
16165  SCIP_BDCHGINFO* bdchginfo;
16166 
16167  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16168  if( bdchginfo != NULL )
16169  return SCIPbdchginfoGetNewbound(bdchginfo);
16170  else
16171  return var->glbdom.ub;
16172  }
16173 
16174  case SCIP_VARSTATUS_FIXED:
16175  return var->glbdom.ub;
16176 
16177  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16178  assert(var->data.aggregate.var != NULL);
16179  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16180  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16181  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16182  * (or is called by) a public interface method; instead, we only assert that values are finite
16183  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16184  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16185  */
16186  if( var->data.aggregate.scalar > 0.0 )
16187  {
16188  /* a > 0 -> get lower bound of y */
16189  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16190  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16191  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16192  + var->data.aggregate.constant;
16193  }
16194  else if( var->data.aggregate.scalar < 0.0 )
16195  {
16196  /* a < 0 -> get upper bound of y */
16197  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16198  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16199  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16200  + var->data.aggregate.constant;
16201  }
16202  else
16203  {
16204  SCIPerrorMessage("scalar is zero in aggregation\n");
16205  SCIPABORT();
16206  return SCIP_INVALID; /*lint !e527*/
16207  }
16208 
16210  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16211  if ( var->data.multaggr.nvars == 1 )
16212  {
16213  assert(var->data.multaggr.vars != NULL);
16214  assert(var->data.multaggr.scalars != NULL);
16215  assert(var->data.multaggr.vars[0] != NULL);
16216 
16217  if( var->data.multaggr.scalars[0] > 0.0 )
16218  {
16219  /* a > 0 -> get lower bound of y */
16220  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16221  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16222  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16223  + var->data.multaggr.constant;
16224  }
16225  else if( var->data.multaggr.scalars[0] < 0.0 )
16226  {
16227  /* a < 0 -> get upper bound of y */
16228  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16229  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16230  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16231  + var->data.multaggr.constant;
16232  }
16233  else
16234  {
16235  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16236  SCIPABORT();
16237  return SCIP_INVALID; /*lint !e527*/
16238  }
16239  }
16240  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16241  SCIPABORT();
16242  return SCIP_INVALID; /*lint !e527*/
16243 
16244  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16245  assert(var->negatedvar != NULL);
16247  assert(var->negatedvar->negatedvar == var);
16248  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16249 
16250  default:
16251  SCIPerrorMessage("unknown variable status\n");
16252  SCIPABORT();
16253  return SCIP_INVALID; /*lint !e527*/
16254  }
16255 }
16256 
16257 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16258  * was applied
16259  *
16260  * @deprecated Please use SCIPgetVarBdAtIndex()
16261  */
16263  SCIP_VAR* var, /**< problem variable */
16264  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16265  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16266  SCIP_Bool after /**< should the bound change with given index be included? */
16267  )
16268 {
16269  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16270  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16271  else
16272  {
16273  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16274  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16275  }
16276 }
16277 
16278 /** returns whether the binary variable was fixed at the time given by the bound change index
16279  *
16280  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16281  */
16283  SCIP_VAR* var, /**< problem variable */
16284  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16285  SCIP_Bool after /**< should the bound change with given index be included? */
16286  )
16287 {
16288  assert(var != NULL);
16289  assert(SCIPvarIsBinary(var));
16290 
16291  /* check the current bounds first in order to decide at which bound change information we have to look
16292  * (which is expensive because we have to follow the aggregation tree to the active variable)
16293  */
16294  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16295  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16296 }
16297 
16298 /** bound change index representing the initial time before any bound changes took place */
16299 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16301 /** bound change index representing the presolving stage */
16302 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16304 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16306  SCIP_VAR* var /**< problem variable */
16307  )
16308 {
16309  SCIP_BDCHGIDX* lbchgidx;
16310  SCIP_BDCHGIDX* ubchgidx;
16311 
16312  assert(var != NULL);
16313 
16314  var = SCIPvarGetProbvar(var);
16315 
16316  /* check, if variable is original without transformed variable */
16317  if( var == NULL )
16318  return &initbdchgidx;
16319 
16320  /* check, if variable was fixed in presolving */
16321  if( !SCIPvarIsActive(var) )
16322  return &presolvebdchgidx;
16323 
16325 
16326  /* get depths of last bound change information for the lower and upper bound */
16327  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16328  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16329  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16330  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16331 
16332  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16333  return ubchgidx;
16334  else
16335  return lbchgidx;
16336 }
16337 
16338 /** returns the last depth level, at which the bounds of the given variable were tightened;
16339  * returns -2, if the variable's bounds are still the global bounds
16340  * returns -1, if the variable was fixed in presolving
16341  */
16343  SCIP_VAR* var /**< problem variable */
16344  )
16345 {
16346  SCIP_BDCHGIDX* bdchgidx;
16347 
16348  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16349  assert(bdchgidx != NULL);
16350 
16351  return bdchgidx->depth;
16352 }
16353 
16354 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16355  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16356  */
16358  SCIP_VAR* var, /**< problem variable */
16359  SCIP_SET* set, /**< global SCIP settings */
16360  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16361  SCIP_Real bound /**< conflicting bound */
16362  )
16363 {
16364  int i;
16365 
16366  assert(var != NULL);
16367  assert(set != NULL);
16368  assert(var->scip == set->scip);
16369 
16370  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16371  {
16372  /* check if the bound is in conflict with the current local bounds */
16373  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16374  return -1;
16375 
16376  /* check if the bound is in conflict with the global bound */
16377  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16378  return 0;
16379 
16380  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16381  assert(var->nubchginfos > 0);
16382  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16383 
16384  /* search for the first conflicting bound change */
16385  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16386  {
16387  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16389  }
16390  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16391  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16392 
16393  /* return the depth at which the first conflicting bound change took place */
16394  return var->ubchginfos[i].bdchgidx.depth;
16395  }
16396  else
16397  {
16398  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16399 
16400  /* check if the bound is in conflict with the current local bounds */
16401  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16402  return -1;
16403 
16404  /* check if the bound is in conflict with the global bound */
16405  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16406  return 0;
16407 
16408  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16409  assert(var->nlbchginfos > 0);
16410  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16411 
16412  /* search for the first conflicting bound change */
16413  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16414  {
16415  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16417  }
16418  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16419  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16420 
16421  /* return the depth at which the first conflicting bound change took place */
16422  return var->lbchginfos[i].bdchgidx.depth;
16423  }
16424 }
16425 
16426 /** returns whether the first binary variable was fixed earlier than the second one;
16427  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16428  * second one is not fixed
16429  */
16431  SCIP_VAR* var1, /**< first binary variable */
16432  SCIP_VAR* var2 /**< second binary variable */
16433  )
16434 {
16435  SCIP_BDCHGIDX* bdchgidx1;
16436  SCIP_BDCHGIDX* bdchgidx2;
16437 
16438  assert(var1 != NULL);
16439  assert(var2 != NULL);
16440  assert(SCIPvarIsBinary(var1));
16441  assert(SCIPvarIsBinary(var2));
16442 
16443  var1 = SCIPvarGetProbvar(var1);
16444  var2 = SCIPvarGetProbvar(var2);
16445  assert(var1 != NULL);
16446  assert(var2 != NULL);
16447 
16448  /* check, if variables are globally fixed */
16449  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16450  return FALSE;
16451  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16452  return TRUE;
16453 
16456  assert(SCIPvarIsBinary(var1));
16457  assert(SCIPvarIsBinary(var2));
16458  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16459  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16460  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16461  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16462  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16463  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16464 
16465  if( var1->nlbchginfos == 1 )
16466  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16467  else if( var1->nubchginfos == 1 )
16468  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16469  else
16470  bdchgidx1 = NULL;
16471 
16472  if( var2->nlbchginfos == 1 )
16473  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16474  else if( var2->nubchginfos == 1 )
16475  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16476  else
16477  bdchgidx2 = NULL;
16478 
16479  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16480 }
16481 
16482 
16483 
16484 /*
16485  * Hash functions
16486  */
16487 
16488 /** gets the key (i.e. the name) of the given variable */
16489 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16490 { /*lint --e{715}*/
16491  SCIP_VAR* var = (SCIP_VAR*)elem;
16492 
16493  assert(var != NULL);
16494  return var->name;
16495 }
16496 
16497 
16498 
16499 
16500 /*
16501  * simple functions implemented as defines
16502  */
16503 
16504 /* In debug mode, the following methods are implemented as function calls to ensure
16505  * type validity.
16506  * In optimized mode, the methods are implemented as defines to improve performance.
16507  * However, we want to have them in the library anyways, so we have to undef the defines.
16508  */
16509 
16510 #undef SCIPboundchgGetNewbound
16511 #undef SCIPboundchgGetVar
16512 #undef SCIPboundchgGetBoundchgtype
16513 #undef SCIPboundchgGetBoundtype
16514 #undef SCIPboundchgIsRedundant
16515 #undef SCIPdomchgGetNBoundchgs
16516 #undef SCIPdomchgGetBoundchg
16517 #undef SCIPholelistGetLeft
16518 #undef SCIPholelistGetRight
16519 #undef SCIPholelistGetNext
16520 #undef SCIPvarGetName
16521 #undef SCIPvarGetNUses
16522 #undef SCIPvarGetData
16523 #undef SCIPvarSetData
16524 #undef SCIPvarSetDelorigData
16525 #undef SCIPvarSetTransData
16526 #undef SCIPvarSetDeltransData
16527 #undef SCIPvarGetStatus
16528 #undef SCIPvarIsOriginal
16529 #undef SCIPvarIsTransformed
16530 #undef SCIPvarIsNegated
16531 #undef SCIPvarGetType
16532 #undef SCIPvarIsBinary
16533 #undef SCIPvarIsIntegral
16534 #undef SCIPvarIsInitial
16535 #undef SCIPvarIsRemovable
16536 #undef SCIPvarIsDeleted
16537 #undef SCIPvarIsDeletable
16538 #undef SCIPvarMarkDeletable
16539 #undef SCIPvarMarkNotDeletable
16540 #undef SCIPvarIsActive
16541 #undef SCIPvarGetIndex
16542 #undef SCIPvarGetProbindex
16543 #undef SCIPvarGetTransVar
16544 #undef SCIPvarGetCol
16545 #undef SCIPvarIsInLP
16546 #undef SCIPvarGetAggrVar
16547 #undef SCIPvarGetAggrScalar
16548 #undef SCIPvarGetAggrConstant
16549 #undef SCIPvarGetMultaggrNVars
16550 #undef SCIPvarGetMultaggrVars
16551 #undef SCIPvarGetMultaggrScalars
16552 #undef SCIPvarGetMultaggrConstant
16553 #undef SCIPvarGetNegatedVar
16554 #undef SCIPvarGetNegationVar
16555 #undef SCIPvarGetNegationConstant
16556 #undef SCIPvarGetObj
16557 #undef SCIPvarGetLbOriginal
16558 #undef SCIPvarGetUbOriginal
16559 #undef SCIPvarGetHolelistOriginal
16560 #undef SCIPvarGetLbGlobal
16561 #undef SCIPvarGetUbGlobal
16562 #undef SCIPvarGetHolelistGlobal
16563 #undef SCIPvarGetBestBoundGlobal
16564 #undef SCIPvarGetWorstBoundGlobal
16565 #undef SCIPvarGetLbLocal
16566 #undef SCIPvarGetUbLocal
16567 #undef SCIPvarGetHolelistLocal
16568 #undef SCIPvarGetBestBoundLocal
16569 #undef SCIPvarGetWorstBoundLocal
16570 #undef SCIPvarGetBestBoundType
16571 #undef SCIPvarGetWorstBoundType
16572 #undef SCIPvarGetLbLazy
16573 #undef SCIPvarGetUbLazy
16574 #undef SCIPvarGetBranchFactor
16575 #undef SCIPvarGetBranchPriority
16576 #undef SCIPvarGetBranchDirection
16577 #undef SCIPvarGetNVlbs
16578 #undef SCIPvarGetVlbVars
16579 #undef SCIPvarGetVlbCoefs
16580 #undef SCIPvarGetVlbConstants
16581 #undef SCIPvarGetNVubs
16582 #undef SCIPvarGetVubVars
16583 #undef SCIPvarGetVubCoefs
16584 #undef SCIPvarGetVubConstants
16585 #undef SCIPvarGetNImpls
16586 #undef SCIPvarGetImplVars
16587 #undef SCIPvarGetImplTypes
16588 #undef SCIPvarGetImplBounds
16589 #undef SCIPvarGetImplIds
16590 #undef SCIPvarGetNCliques
16591 #undef SCIPvarGetCliques
16592 #undef SCIPvarGetLPSol
16593 #undef SCIPvarGetNLPSol
16594 #undef SCIPvarGetBdchgInfoLb
16595 #undef SCIPvarGetNBdchgInfosLb
16596 #undef SCIPvarGetBdchgInfoUb
16597 #undef SCIPvarGetNBdchgInfosUb
16598 #undef SCIPvarGetValuehistory
16599 #undef SCIPvarGetPseudoSol
16600 #undef SCIPvarCatchEvent
16601 #undef SCIPvarDropEvent
16602 #undef SCIPvarGetVSIDS
16603 #undef SCIPvarGetCliqueComponentIdx
16604 #undef SCIPbdchgidxGetPos
16605 #undef SCIPbdchgidxIsEarlierNonNull
16606 #undef SCIPbdchgidxIsEarlier
16607 #undef SCIPbdchginfoGetOldbound
16608 #undef SCIPbdchginfoGetNewbound
16609 #undef SCIPbdchginfoGetVar
16610 #undef SCIPbdchginfoGetChgtype
16611 #undef SCIPbdchginfoGetBoundtype
16612 #undef SCIPbdchginfoGetDepth
16613 #undef SCIPbdchginfoGetPos
16614 #undef SCIPbdchginfoGetIdx
16615 #undef SCIPbdchginfoGetInferVar
16616 #undef SCIPbdchginfoGetInferCons
16617 #undef SCIPbdchginfoGetInferProp
16618 #undef SCIPbdchginfoGetInferInfo
16619 #undef SCIPbdchginfoGetInferBoundtype
16620 #undef SCIPbdchginfoIsRedundant
16621 #undef SCIPbdchginfoHasInferenceReason
16622 #undef SCIPbdchginfoIsTighter
16623 
16624 
16625 /** returns the new value of the bound in the bound change data */
16627  SCIP_BOUNDCHG* boundchg /**< bound change data */
16628  )
16629 {
16630  assert(boundchg != NULL);
16631 
16632  return boundchg->newbound;
16633 }
16634 
16635 /** returns the variable of the bound change in the bound change data */
16637  SCIP_BOUNDCHG* boundchg /**< bound change data */
16638  )
16639 {
16640  assert(boundchg != NULL);
16641 
16642  return boundchg->var;
16643 }
16644 
16645 /** returns the bound change type of the bound change in the bound change data */
16647  SCIP_BOUNDCHG* boundchg /**< bound change data */
16648  )
16649 {
16650  assert(boundchg != NULL);
16651 
16652  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16653 }
16654 
16655 /** returns the bound type of the bound change in the bound change data */
16657  SCIP_BOUNDCHG* boundchg /**< bound change data */
16658  )
16659 {
16660  assert(boundchg != NULL);
16661 
16662  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16663 }
16664 
16665 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16667  SCIP_BOUNDCHG* boundchg /**< bound change data */
16668  )
16669 {
16670  assert(boundchg != NULL);
16671 
16672  return boundchg->redundant;
16673 }
16674 
16675 /** returns the number of bound changes in the domain change data */
16677  SCIP_DOMCHG* domchg /**< domain change data */
16678  )
16679 {
16680  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16681 }
16682 
16683 /** returns a particular bound change in the domain change data */
16685  SCIP_DOMCHG* domchg, /**< domain change data */
16686  int pos /**< position of the bound change in the domain change data */
16687  )
16688 {
16689  assert(domchg != NULL);
16690  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16691 
16692  return &domchg->domchgbound.boundchgs[pos];
16693 }
16694 
16695 /** returns left bound of open interval in hole */
16697  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16698  )
16699 {
16700  assert(holelist != NULL);
16701 
16702  return holelist->hole.left;
16703 }
16704 
16705 /** returns right bound of open interval in hole */
16707  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16708  )
16709 {
16710  assert(holelist != NULL);
16711 
16712  return holelist->hole.right;
16713 }
16714 
16715 /** returns next hole in list */
16717  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16718  )
16719 {
16720  assert(holelist != NULL);
16721 
16722  return holelist->next;
16723 }
16724 
16725 /** returns the name of the variable
16726  *
16727  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16728  */
16729 const char* SCIPvarGetName(
16730  SCIP_VAR* var /**< problem variable */
16731  )
16732 {
16733  assert(var != NULL);
16734 
16735  return var->name;
16736 }
16737 
16738 /** gets number of times, the variable is currently captured */
16739 int SCIPvarGetNUses(
16740  SCIP_VAR* var /**< problem variable */
16741  )
16742 {
16743  assert(var != NULL);
16744 
16745  return var->nuses;
16746 }
16747 
16748 /** returns the user data of the variable */
16750  SCIP_VAR* var /**< problem variable */
16751  )
16752 {
16753  assert(var != NULL);
16754 
16755  return var->vardata;
16756 }
16757 
16758 /** sets the user data for the variable */
16759 void SCIPvarSetData(
16760  SCIP_VAR* var, /**< problem variable */
16761  SCIP_VARDATA* vardata /**< user variable data */
16762  )
16763 {
16764  assert(var != NULL);
16765 
16766  var->vardata = vardata;
16767 }
16768 
16769 /** sets method to free user data for the original variable */
16771  SCIP_VAR* var, /**< problem variable */
16772  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16773  )
16774 {
16775  assert(var != NULL);
16776  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16777 
16778  var->vardelorig = vardelorig;
16779 }
16780 
16781 /** sets method to transform user data of the variable */
16782 void SCIPvarSetTransData(
16783  SCIP_VAR* var, /**< problem variable */
16784  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16785  )
16786 {
16787  assert(var != NULL);
16788  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16789 
16790  var->vartrans = vartrans;
16791 }
16792 
16793 /** sets method to free transformed user data for the variable */
16795  SCIP_VAR* var, /**< problem variable */
16796  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16797  )
16798 {
16799  assert(var != NULL);
16800 
16801  var->vardeltrans = vardeltrans;
16802 }
16803 
16804 /** sets method to copy this variable into sub-SCIPs */
16805 void SCIPvarSetCopyData(
16806  SCIP_VAR* var, /**< problem variable */
16807  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16808  )
16809 {
16810  assert(var != NULL);
16811 
16812  var->varcopy = varcopy;
16813 }
16814 
16815 /** sets the initial flag of a variable; only possible for original or loose variables */
16817  SCIP_VAR* var, /**< problem variable */
16818  SCIP_Bool initial /**< initial flag */
16819  )
16820 {
16821  assert(var != NULL);
16822 
16824  return SCIP_INVALIDCALL;
16825 
16826  var->initial = initial;
16827 
16828  return SCIP_OKAY;
16829 }
16830 
16831 /** sets the removable flag of a variable; only possible for original or loose variables */
16833  SCIP_VAR* var, /**< problem variable */
16834  SCIP_Bool removable /**< removable flag */
16835  )
16836 {
16837  assert(var != NULL);
16838 
16840  return SCIP_INVALIDCALL;
16841 
16842  var->removable = removable;
16843 
16844  return SCIP_OKAY;
16845 }
16846 
16847 /** gets status of variable */
16849  SCIP_VAR* var /**< problem variable */
16850  )
16851 {
16852  assert(var != NULL);
16853 
16854  return (SCIP_VARSTATUS)(var->varstatus);
16855 }
16856 
16857 /** returns whether the variable belongs to the original problem */
16859  SCIP_VAR* var /**< problem variable */
16860  )
16861 {
16862  assert(var != NULL);
16863  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16864 
16868 }
16869 
16870 /** returns whether the variable belongs to the transformed problem */
16872  SCIP_VAR* var /**< problem variable */
16873  )
16874 {
16875  assert(var != NULL);
16876  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16877 
16881 }
16882 
16883 /** returns whether the variable was created by negation of a different variable */
16885  SCIP_VAR* var /**< problem variable */
16886  )
16887 {
16888  assert(var != NULL);
16889 
16890  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16891 }
16892 
16893 /** gets type of variable */
16895  SCIP_VAR* var /**< problem variable */
16896  )
16897 {
16898  assert(var != NULL);
16899 
16900  return (SCIP_VARTYPE)(var->vartype);
16901 }
16902 
16903 /** returns TRUE if the variable is of binary type; this is the case if:
16904  * (1) variable type is binary
16905  * (2) variable type is integer or implicit integer and
16906  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16907  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16908  */
16910  SCIP_VAR* var /**< problem variable */
16911  )
16912 {
16913  assert(var != NULL);
16914 
16915  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16916  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16917 }
16918 
16919 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16921  SCIP_VAR* var /**< problem variable */
16922  )
16923 {
16924  assert(var != NULL);
16925 
16926  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16927 }
16928 
16929 /** returns whether variable's column should be present in the initial root LP */
16931  SCIP_VAR* var /**< problem variable */
16932  )
16933 {
16934  assert(var != NULL);
16935 
16936  return var->initial;
16937 }
16938 
16939 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16941  SCIP_VAR* var /**< problem variable */
16942  )
16943 {
16944  assert(var != NULL);
16945 
16946  return var->removable;
16947 }
16948 
16949 /** returns whether the variable was deleted from the problem */
16951  SCIP_VAR* var /**< problem variable */
16952  )
16953 {
16954  assert(var != NULL);
16955 
16956  return var->deleted;
16957 }
16958 
16959 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16960  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16961  */
16963  SCIP_VAR* var /**< problem variable */
16964  )
16965 {
16966  assert(var != NULL);
16967  assert(var->probindex == -1);
16968 
16969  var->deletable = TRUE;
16970 }
16971 
16972 /** marks the variable to be not deletable from the problem */
16975  )
16976 {
16977  assert(var != NULL);
16978 
16979  var->deletable = FALSE;
16980 }
16981 
16982 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16983  *
16984  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16985  */
16987  SCIP_VAR* var /**< problem variable */
16988  )
16989 {
16990  assert(var != NULL);
16991 
16992  var->delglobalstructs = TRUE;
16993 }
16994 
16995 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16997  SCIP_VAR* var /**< problem variable */
16998  )
16999 {
17000  assert(var != NULL);
17001 
17002  return var->delglobalstructs;
17003 }
17004 
17005 /** returns whether variable is allowed to be deleted completely from the problem */
17008  )
17009 {
17010  assert(var != NULL);
17011 
17012  return var->deletable;
17013 }
17014 
17015 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17017  SCIP_VAR* var /**< problem variable */
17018  )
17019 {
17020  assert(var != NULL);
17021 
17022  return (var->probindex >= 0);
17023 }
17024 
17025 /** gets unique index of variable */
17026 int SCIPvarGetIndex(
17027  SCIP_VAR* var /**< problem variable */
17028  )
17029 {
17030  assert(var != NULL);
17031 
17032  return var->index;
17033 }
17034 
17035 /** gets position of variable in problem, or -1 if variable is not active */
17037  SCIP_VAR* var /**< problem variable */
17038  )
17039 {
17040  assert(var != NULL);
17041 
17042  return var->probindex;
17043 }
17044 
17045 /** gets transformed variable of ORIGINAL variable */
17047  SCIP_VAR* var /**< problem variable */
17048  )
17049 {
17050  assert(var != NULL);
17051  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17052 
17053  return var->data.original.transvar;
17054 }
17055 
17056 /** gets column of COLUMN variable */
17058  SCIP_VAR* var /**< problem variable */
17059  )
17060 {
17061  assert(var != NULL);
17062  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17063 
17064  return var->data.col;
17065 }
17066 
17067 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17069  SCIP_VAR* var /**< problem variable */
17070  )
17071 {
17072  assert(var != NULL);
17073 
17074  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17075 }
17076 
17077 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17079  SCIP_VAR* var /**< problem variable */
17080  )
17081 {
17082  assert(var != NULL);
17084 
17085  return var->data.aggregate.var;
17086 }
17087 
17088 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17090  SCIP_VAR* var /**< problem variable */
17091  )
17092 {
17093  assert(var != NULL);
17095 
17096  return var->data.aggregate.scalar;
17097 }
17098 
17099 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17101  SCIP_VAR* var /**< problem variable */
17102  )
17103 {
17104  assert(var != NULL);
17106 
17107  return var->data.aggregate.constant;
17108 }
17109 
17110 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17112  SCIP_VAR* var /**< problem variable */
17113  )
17114 {
17115  assert(var != NULL);
17116  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17117  assert(!var->donotmultaggr);
17118 
17119  return var->data.multaggr.nvars;
17120 }
17121 
17122 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17124  SCIP_VAR* var /**< problem variable */
17125  )
17126 {
17127  assert(var != NULL);
17128  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17129  assert(!var->donotmultaggr);
17130 
17131  return var->data.multaggr.vars;
17132 }
17133 
17134 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17136  SCIP_VAR* var /**< problem variable */
17137  )
17138 {
17139  assert(var != NULL);
17140  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17141  assert(!var->donotmultaggr);
17142 
17143  return var->data.multaggr.scalars;
17144 }
17145 
17146 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17148  SCIP_VAR* var /**< problem variable */
17149  )
17150 {
17151  assert(var != NULL);
17152  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17153  assert(!var->donotmultaggr);
17154 
17155  return var->data.multaggr.constant;
17156 }
17157 
17158 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17160  SCIP_VAR* var /**< negated problem variable */
17161  )
17162 {
17163  assert(var != NULL);
17164 
17165  return var->negatedvar;
17166 }
17167 
17168 /** gets the negation variable x of a negated variable x' = offset - x */
17170  SCIP_VAR* var /**< negated problem variable */
17171  )
17172 {
17173  assert(var != NULL);
17174  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17175 
17176  return var->negatedvar;
17177 }
17178 
17179 /** gets the negation offset of a negated variable x' = offset - x */
17181  SCIP_VAR* var /**< negated problem variable */
17182  )
17183 {
17184  assert(var != NULL);
17185  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17186 
17187  return var->data.negate.constant;
17188 }
17189 
17190 /** gets objective function value of variable */
17192  SCIP_VAR* var /**< problem variable */
17193  )
17194 {
17195  assert(var != NULL);
17196 
17197  return var->obj;
17198 }
17199 
17200 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17202  SCIP_VAR* var /**< problem variable */
17203  )
17204 {
17205  assert(var != NULL);
17206 
17207  return var->unchangedobj;
17208 }
17209 
17210 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17211  * e.g. obj(x) = 1 this method returns for ~x the value -1
17212  */
17214  SCIP_VAR* var, /**< problem variable */
17215  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17216  )
17217 {
17218  SCIP_VAR* probvar = var;
17219  SCIP_Real mult = 1.0;
17220 
17221  assert(probvar != NULL);
17222  assert(aggrobj != NULL);
17223 
17224  while( probvar != NULL )
17225  {
17226  switch( SCIPvarGetStatus(probvar) )
17227  {
17229  case SCIP_VARSTATUS_LOOSE:
17230  case SCIP_VARSTATUS_COLUMN:
17231  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17232  return SCIP_OKAY;
17233 
17234  case SCIP_VARSTATUS_FIXED:
17235  assert(SCIPvarGetObj(probvar) == 0.0);
17236  (*aggrobj) = 0.0;
17237  return SCIP_OKAY;
17238 
17240  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17241  if ( probvar->data.multaggr.nvars == 1 )
17242  {
17243  assert( probvar->data.multaggr.vars != NULL );
17244  assert( probvar->data.multaggr.scalars != NULL );
17245  assert( probvar->data.multaggr.vars[0] != NULL );
17246  mult *= probvar->data.multaggr.scalars[0];
17247  probvar = probvar->data.multaggr.vars[0];
17248  break;
17249  }
17250  else
17251  {
17252  SCIP_Real tmpobj;
17253  int v;
17254 
17255  (*aggrobj) = 0.0;
17256 
17257  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17258  {
17259  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17260  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17261  }
17262  return SCIP_OKAY;
17263  }
17264 
17265  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17266  assert(probvar->data.aggregate.var != NULL);
17267  mult *= probvar->data.aggregate.scalar;
17268  probvar = probvar->data.aggregate.var;
17269  break;
17270 
17271  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17272  assert(probvar->negatedvar != NULL);
17273  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17274  assert(probvar->negatedvar->negatedvar == probvar);
17275  mult *= -1.0;
17276  probvar = probvar->negatedvar;
17277  break;
17278 
17279  default:
17280  SCIPABORT();
17281  return SCIP_INVALIDDATA; /*lint !e527*/
17282  }
17283  }
17284 
17285  return SCIP_INVALIDDATA;
17286 }
17287 
17288 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17290  SCIP_VAR* var /**< original problem variable */
17291  )
17292 {
17293  assert(var != NULL);
17294  assert(SCIPvarIsOriginal(var));
17295 
17297  return var->data.original.origdom.lb;
17298  else
17299  {
17300  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17301  assert(var->negatedvar != NULL);
17303 
17304  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17305  }
17306 }
17307 
17308 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17310  SCIP_VAR* var /**< original problem variable */
17311  )
17312 {
17313  assert(var != NULL);
17314  assert(SCIPvarIsOriginal(var));
17315 
17317  return var->data.original.origdom.ub;
17318  else
17319  {
17320  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17321  assert(var->negatedvar != NULL);
17323 
17324  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17325  }
17326 }
17327 
17328 /** gets the original hole list of an original variable */
17330  SCIP_VAR* var /**< problem variable */
17331  )
17332 {
17333  assert(var != NULL);
17334  assert(SCIPvarIsOriginal(var));
17335 
17337  return var->data.original.origdom.holelist;
17338 
17339  return NULL;
17340 }
17341 
17342 /** gets global lower bound of variable */
17344  SCIP_VAR* var /**< problem variable */
17345  )
17346 {
17347  assert(var != NULL);
17348 
17349  return var->glbdom.lb;
17350 }
17351 
17352 /** gets global upper bound of variable */
17354  SCIP_VAR* var /**< problem variable */
17355  )
17356 {
17357  assert(var != NULL);
17358 
17359  return var->glbdom.ub;
17360 }
17361 
17362 /** gets the global hole list of an active variable */
17364  SCIP_VAR* var /**< problem variable */
17365  )
17366 {
17367  assert(var != NULL);
17368 
17369  return var->glbdom.holelist;
17370 }
17371 
17372 /** gets best global bound of variable with respect to the objective function */
17374  SCIP_VAR* var /**< problem variable */
17375  )
17376 {
17377  assert(var != NULL);
17378 
17379  if( var->obj >= 0.0 )
17380  return var->glbdom.lb;
17381  else
17382  return var->glbdom.ub;
17383 }
17384 
17385 /** gets worst global bound of variable with respect to the objective function */
17387  SCIP_VAR* var /**< problem variable */
17388  )
17389 {
17390  assert(var != NULL);
17391 
17392  if( var->obj >= 0.0 )
17393  return var->glbdom.ub;
17394  else
17395  return var->glbdom.lb;
17396 }
17397 
17398 /** gets current lower bound of variable */
17400  SCIP_VAR* var /**< problem variable */
17401  )
17402 {
17403  assert(var != NULL);
17404 
17405  return var->locdom.lb;
17406 }
17407 
17408 /** gets current upper bound of variable */
17410  SCIP_VAR* var /**< problem variable */
17411  )
17412 {
17413  assert(var != NULL);
17414 
17415  return var->locdom.ub;
17416 }
17417 
17418 /** gets the current hole list of an active variable */
17420  SCIP_VAR* var /**< problem variable */
17421  )
17422 {
17423  assert(var != NULL);
17424 
17425  return var->locdom.holelist;
17426 }
17427 
17428 /** gets best local bound of variable with respect to the objective function */
17430  SCIP_VAR* var /**< problem variable */
17431  )
17432 {
17433  assert(var != NULL);
17434 
17435  if( var->obj >= 0.0 )
17436  return var->locdom.lb;
17437  else
17438  return var->locdom.ub;
17439 }
17440 
17441 /** gets worst local bound of variable with respect to the objective function */
17443  SCIP_VAR* var /**< problem variable */
17444  )
17445 {
17446  assert(var != NULL);
17447 
17448  if( var->obj >= 0.0 )
17449  return var->locdom.ub;
17450  else
17451  return var->locdom.lb;
17452 }
17453 
17454 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17456  SCIP_VAR* var /**< problem variable */
17457  )
17458 {
17459  assert(var != NULL);
17460 
17461  if( var->obj >= 0.0 )
17462  return SCIP_BOUNDTYPE_LOWER;
17463  else
17464  return SCIP_BOUNDTYPE_UPPER;
17465 }
17466 
17467 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17469  SCIP_VAR* var /**< problem variable */
17470  )
17471 {
17472  assert(var != NULL);
17473 
17474  if( var->obj >= 0.0 )
17475  return SCIP_BOUNDTYPE_UPPER;
17476  else
17477  return SCIP_BOUNDTYPE_LOWER;
17478 }
17479 
17480 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17482  SCIP_VAR* var /**< problem variable */
17483  )
17484 {
17485  assert(var != NULL);
17486 
17487  return var->lazylb;
17488 }
17489 
17490 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17492  SCIP_VAR* var /**< problem variable */
17493  )
17494 {
17495  assert(var != NULL);
17496 
17497  return var->lazyub;
17498 }
17499 
17500 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17501  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17502  */
17504  SCIP_VAR* var /**< problem variable */
17505  )
17506 {
17507  assert(var != NULL);
17508 
17509  return var->branchfactor;
17510 }
17511 
17512 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17513  * with lower priority
17514  */
17516  SCIP_VAR* var /**< problem variable */
17517  )
17518 {
17519  assert(var != NULL);
17520 
17521  return var->branchpriority;
17522 }
17523 
17524 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17526  SCIP_VAR* var /**< problem variable */
17527  )
17528 {
17529  assert(var != NULL);
17530 
17531  return (SCIP_BRANCHDIR)var->branchdirection;
17532 }
17533 
17534 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17535 int SCIPvarGetNVlbs(
17536  SCIP_VAR* var /**< problem variable */
17537  )
17538 {
17539  assert(var != NULL);
17540 
17541  return SCIPvboundsGetNVbds(var->vlbs);
17542 }
17543 
17544 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17545  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17546  */
17548  SCIP_VAR* var /**< problem variable */
17549  )
17550 {
17551  assert(var != NULL);
17552 
17553  return SCIPvboundsGetVars(var->vlbs);
17554 }
17555 
17556 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17558  SCIP_VAR* var /**< problem variable */
17559  )
17560 {
17561  assert(var != NULL);
17562 
17563  return SCIPvboundsGetCoefs(var->vlbs);
17564 }
17565 
17566 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17568  SCIP_VAR* var /**< problem variable */
17569  )
17570 {
17571  assert(var != NULL);
17572 
17573  return SCIPvboundsGetConstants(var->vlbs);
17574 }
17575 
17576 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17577 int SCIPvarGetNVubs(
17578  SCIP_VAR* var /**< problem variable */
17579  )
17580 {
17581  assert(var != NULL);
17582 
17583  return SCIPvboundsGetNVbds(var->vubs);
17584 }
17585 
17586 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17587  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17588  */
17590  SCIP_VAR* var /**< problem variable */
17591  )
17592 {
17593  assert(var != NULL);
17594 
17595  return SCIPvboundsGetVars(var->vubs);
17596 }
17597 
17598 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17600  SCIP_VAR* var /**< problem variable */
17601  )
17602 {
17603  assert(var != NULL);
17604 
17605  return SCIPvboundsGetCoefs(var->vubs);
17606 }
17607 
17608 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17610  SCIP_VAR* var /**< problem variable */
17611  )
17612 {
17613  assert(var != NULL);
17614 
17615  return SCIPvboundsGetConstants(var->vubs);
17616 }
17617 
17618 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17619  * there are no implications for nonbinary variable x
17620  */
17621 int SCIPvarGetNImpls(
17622  SCIP_VAR* var, /**< active problem variable */
17623  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17624  )
17625 {
17626  assert(var != NULL);
17627  assert(SCIPvarIsActive(var));
17628 
17629  return SCIPimplicsGetNImpls(var->implics, varfixing);
17630 }
17631 
17632 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17633  * problem variable x, there are no implications for nonbinary variable x;
17634  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17635  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17636  * (see SCIPvarGetIndex())
17637  */
17639  SCIP_VAR* var, /**< active problem variable */
17640  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17641  )
17642 {
17643  assert(var != NULL);
17644  assert(SCIPvarIsActive(var));
17645 
17646  return SCIPimplicsGetVars(var->implics, varfixing);
17647 }
17648 
17649 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17650  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17651  * there are no implications for nonbinary variable x
17652  */
17654  SCIP_VAR* var, /**< active problem variable */
17655  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17656  )
17657 {
17658  assert(var != NULL);
17659  assert(SCIPvarIsActive(var));
17660 
17661  return SCIPimplicsGetTypes(var->implics, varfixing);
17662 }
17663 
17664 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17665  * variable x, there are no implications for nonbinary variable x
17666  */
17668  SCIP_VAR* var, /**< active problem variable */
17669  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17670  )
17671 {
17672  assert(var != NULL);
17673  assert(SCIPvarIsActive(var));
17674 
17675  return SCIPimplicsGetBounds(var->implics, varfixing);
17676 }
17677 
17678 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17679  * there are no implications for nonbinary variable x.
17680  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17681  * its id is negative, otherwise it is nonnegative.
17682  */
17683 int* SCIPvarGetImplIds(
17684  SCIP_VAR* var, /**< active problem variable */
17685  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17686  )
17687 {
17688  assert(var != NULL);
17689  assert(SCIPvarIsActive(var));
17690 
17691  return SCIPimplicsGetIds(var->implics, varfixing);
17692 }
17693 
17694 /** gets number of cliques, the active variable is contained in */
17695 int SCIPvarGetNCliques(
17696  SCIP_VAR* var, /**< active problem variable */
17697  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17698  )
17699 {
17700  assert(var != NULL);
17701 
17702  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17703 }
17704 
17705 /** gets array of cliques, the active variable is contained in */
17707  SCIP_VAR* var, /**< active problem variable */
17708  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17709  )
17710 {
17711  assert(var != NULL);
17712 
17713  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17714 }
17715 
17716 /** gets primal LP solution value of variable */
17718  SCIP_VAR* var /**< problem variable */
17719  )
17720 {
17721  assert(var != NULL);
17722 
17724  return SCIPcolGetPrimsol(var->data.col);
17725  else
17726  return SCIPvarGetLPSol_rec(var);
17727 }
17728 
17729 /** gets primal NLP solution value of variable */
17731  SCIP_VAR* var /**< problem variable */
17732  )
17733 {
17734  assert(var != NULL);
17735 
17737  return var->nlpsol;
17738  else
17739  return SCIPvarGetNLPSol_rec(var);
17740 }
17741 
17742 /** return lower bound change info at requested position */
17744  SCIP_VAR* var, /**< problem variable */
17745  int pos /**< requested position */
17746  )
17747 {
17748  assert(pos >= 0);
17749  assert(pos < var->nlbchginfos);
17750 
17751  return &var->lbchginfos[pos];
17752 }
17753 
17754 /** gets the number of lower bound change info array */
17756  SCIP_VAR* var /**< problem variable */
17757  )
17758 {
17759  return var->nlbchginfos;
17760 }
17761 
17762 /** return upper bound change info at requested position */
17764  SCIP_VAR* var, /**< problem variable */
17765  int pos /**< requested position */
17766  )
17767 {
17768  assert(pos >= 0);
17769  assert(pos < var->nubchginfos);
17770 
17771  return &var->ubchginfos[pos];
17772 }
17773 
17774 /** gets the number upper bound change info array */
17776  SCIP_VAR* var /**< problem variable */
17777  )
17778 {
17779  assert(var != NULL);
17780 
17781  return var->nubchginfos;
17782 }
17783 
17784 /** returns the value based history for the variable */
17786  SCIP_VAR* var /**< problem variable */
17787  )
17788 {
17789  assert(var != NULL);
17790 
17791  return var->valuehistory;
17792 }
17793 
17794 /** gets pseudo solution value of variable */
17796  SCIP_VAR* var /**< problem variable */
17797  )
17798 {
17799  assert(var != NULL);
17800 
17802  return SCIPvarGetBestBoundLocal(var);
17803  else
17804  return SCIPvarGetPseudoSol_rec(var);
17805 }
17806 
17807 /** returns the variable's VSIDS score */
17809  SCIP_VAR* var, /**< problem variable */
17810  SCIP_STAT* stat, /**< problem statistics */
17811  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17812  )
17813 {
17814  assert(var != NULL);
17815 
17817  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17818  else
17819  return SCIPvarGetVSIDS_rec(var, stat, dir);
17820 }
17821 
17822 /** includes event handler with given data in variable's event filter */
17824  SCIP_VAR* var, /**< problem variable */
17825  BMS_BLKMEM* blkmem, /**< block memory */
17826  SCIP_SET* set, /**< global SCIP settings */
17827  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17828  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17829  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17830  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17831  )
17832 {
17833  assert(var != NULL);
17834  assert(set != NULL);
17835  assert(var->scip == set->scip);
17836  assert(var->eventfilter != NULL);
17837  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17838  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17839  assert(SCIPvarIsTransformed(var));
17840 
17841  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
17842  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17843 
17844  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17845 
17846  return SCIP_OKAY;
17847 }
17848 
17849 /** deletes event handler with given data from variable's event filter */
17851  SCIP_VAR* var, /**< problem variable */
17852  BMS_BLKMEM* blkmem, /**< block memory */
17853  SCIP_SET* set, /**< global SCIP settings */
17854  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17855  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17856  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17857  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17858  )
17859 {
17860  assert(var != NULL);
17861  assert(set != NULL);
17862  assert(var->scip == set->scip);
17863  assert(var->eventfilter != NULL);
17864  assert(SCIPvarIsTransformed(var));
17865 
17866  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17867  (void*)eventdata);
17868 
17869  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17870 
17871  return SCIP_OKAY;
17872 }
17873 
17874 /** returns the position of the bound change index */
17875 int SCIPbdchgidxGetPos(
17876  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17877  )
17878 {
17879  assert(bdchgidx != NULL);
17880 
17881  return bdchgidx->pos;
17882 }
17883 
17884 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17886  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17887  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17888  )
17889 {
17890  assert(bdchgidx1 != NULL);
17891  assert(bdchgidx1->depth >= -2);
17892  assert(bdchgidx1->pos >= 0);
17893  assert(bdchgidx2 != NULL);
17894  assert(bdchgidx2->depth >= -2);
17895  assert(bdchgidx2->pos >= 0);
17896 
17897  return (bdchgidx1->depth < bdchgidx2->depth)
17898  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17899 }
17900 
17901 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17902  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17903  * last bound change was applied to the current node
17904  */
17906  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17907  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17908  )
17909 {
17910  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17911  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17912  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17913  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17914 
17915  if( bdchgidx1 == NULL )
17916  return FALSE;
17917  else if( bdchgidx2 == NULL )
17918  return TRUE;
17919  else
17920  return (bdchgidx1->depth < bdchgidx2->depth)
17921  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17922 }
17923 
17924 /** returns old bound that was overwritten for given bound change information */
17926  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17927  )
17928 {
17929  assert(bdchginfo != NULL);
17930 
17931  return bdchginfo->oldbound;
17932 }
17933 
17934 /** returns new bound installed for given bound change information */
17936  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17937  )
17938 {
17939  assert(bdchginfo != NULL);
17940 
17941  return bdchginfo->newbound;
17942 }
17943 
17944 /** returns variable that belongs to the given bound change information */
17946  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17947  )
17948 {
17949  assert(bdchginfo != NULL);
17950 
17951  return bdchginfo->var;
17952 }
17953 
17954 /** returns whether the bound change information belongs to a branching decision or a deduction */
17956  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17957  )
17958 {
17959  assert(bdchginfo != NULL);
17960 
17961  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17962 }
17963 
17964 /** returns whether the bound change information belongs to a lower or upper bound change */
17966  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17967  )
17968 {
17969  assert(bdchginfo != NULL);
17970 
17971  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17972 }
17973 
17974 /** returns depth level of given bound change information */
17976  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17977  )
17978 {
17979  assert(bdchginfo != NULL);
17980 
17981  return bdchginfo->bdchgidx.depth;
17982 }
17983 
17984 /** returns bound change position in its depth level of given bound change information */
17986  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17987  )
17988 {
17989  assert(bdchginfo != NULL);
17990 
17991  return bdchginfo->bdchgidx.pos;
17992 }
17993 
17994 /** returns bound change index of given bound change information */
17996  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17997  )
17998 {
17999  assert(bdchginfo != NULL);
18000 
18001  return &bdchginfo->bdchgidx;
18002 }
18003 
18004 /** returns inference variable of given bound change information */
18006  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18007  )
18008 {
18009  assert(bdchginfo != NULL);
18012 
18013  return bdchginfo->inferencedata.var;
18014 }
18015 
18016 /** returns inference constraint of given bound change information */
18018  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18019  )
18020 {
18021  assert(bdchginfo != NULL);
18023  assert(bdchginfo->inferencedata.reason.cons != NULL);
18024 
18025  return bdchginfo->inferencedata.reason.cons;
18026 }
18027 
18028 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18030  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18031  )
18032 {
18033  assert(bdchginfo != NULL);
18035 
18036  return bdchginfo->inferencedata.reason.prop;
18037 }
18038 
18039 /** returns inference user information of given bound change information */
18041  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18042  )
18043 {
18044  assert(bdchginfo != NULL);
18047 
18048  return bdchginfo->inferencedata.info;
18049 }
18050 
18051 /** returns inference bound of inference variable of given bound change information */
18053  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18054  )
18055 {
18056  assert(bdchginfo != NULL);
18059 
18060  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18061 }
18062 
18063 /** returns the relaxed bound change type */
18065  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18066  )
18067 {
18068  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18069 }
18070 
18071 
18072 /** returns whether the bound change information belongs to a redundant bound change */
18074  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18075  )
18076 {
18077  assert(bdchginfo != NULL);
18078  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18079 
18080  return bdchginfo->redundant;
18081 }
18082 
18083 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18085  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18086  )
18087 {
18088  assert(bdchginfo != NULL);
18089 
18092  && bdchginfo->inferencedata.reason.prop != NULL);
18093 }
18094 
18095 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18096  * has a tighter new bound as the second bound change
18097  */
18099  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18100  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18101  )
18102 {
18103  assert(bdchginfo1 != NULL);
18104  assert(bdchginfo2 != NULL);
18105  assert(bdchginfo1->var == bdchginfo2->var);
18106  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18107 
18108  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18109  ? bdchginfo1->newbound > bdchginfo2->newbound
18110  : bdchginfo1->newbound < bdchginfo2->newbound);
18111 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:554
SCIP_HOLELIST * holelist
Definition: struct_var.h:163
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1734
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18065
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1656
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1514
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14884
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17443
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5953
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17558
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:456
#define NULL
Definition: def.h:246
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13604
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:928
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17469
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9090
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:15011
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10964
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:87
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:567
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3343
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6011
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6461
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:486
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:14531
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8972
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:10081
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16263
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18030
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16974
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12764
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13488
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3176
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17467
int nubchginfos
Definition: struct_var.h:263
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:6051
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17744
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17136
union SCIP_BoundChg::@12 data
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:112
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:599
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15792
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:227
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5855
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17504
unsigned int inferboundtype
Definition: struct_var.h:93
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17926
char * name
Definition: struct_var.h:229
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:965
unsigned int boundchgtype
Definition: struct_var.h:114
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17526
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:1124
SCIP_HOLE hole
Definition: struct_var.h:51
SCIP_Real bestrootsol
Definition: struct_var.h:207
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17492
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6140
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:6545
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6351
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17536
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17946
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1906
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17387
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:138
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:6895
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5667
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:2044
public methods for implications, variable bounds, and cliques
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14098
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:4570
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16343
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:2153
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17344
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15267
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11796
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1445
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14264
#define SCIP_MAXSTRLEN
Definition: def.h:267
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3233
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16718
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16931
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:802
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3294
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6277
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:583
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6076
SCIP_Real lastbranchvalue
Definition: struct_stat.h:131
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1035
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17124
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:272
#define MAXABSVBCOEF
Definition: var.c:70
#define SQR(x)
Definition: def.h:198
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1915
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12898
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15846
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:1892
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17400
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7179
SCIP_Real constant
Definition: struct_var.h:184
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17707
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1176
SCIP_Real bestrootredcost
Definition: struct_var.h:208
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8274
SCIP_HISTORY * historycrun
Definition: struct_var.h:245
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:171
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17786
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3409
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7627
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1425
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16783
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6336
SCIP_Longint closestvblpcount
Definition: struct_var.h:247
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:8582
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:2413
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16910
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:6472
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3261
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5813
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:154
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3635
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12741
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2310
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:243
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17906
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16283
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17430
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12834
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:836
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5890
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14617
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12418
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:128
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16657
unsigned int nboundchgs
Definition: struct_var.h:123
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:17824
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:3216
SCIP_HOLELIST * newlist
Definition: struct_var.h:59
SCIP_Real right
Definition: struct_var.h:45
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:313
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5810
#define NLOCKTYPES
Definition: type_var.h:81
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:41
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:4380
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16717
#define FALSE
Definition: def.h:72
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:182
#define EPSISINT(x, eps)
Definition: def.h:194
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17457
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6494
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17756
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:480
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:107
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 SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16660
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:751
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3340
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:68
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16640
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:258
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3035
SCIP_Real constant
Definition: struct_var.h:194
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10253
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6065
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:278
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14503
#define TRUE
Definition: def.h:71
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10635
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5791
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14840
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:111
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_HOLELIST * oldlist
Definition: struct_var.h:60
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17181
#define MAXIMPLSCLOSURE
Definition: var.c:67
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17578
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:688
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18041
int nlbchginfos
Definition: struct_var.h:261
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16303
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2860
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1904
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:2001
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17037
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:10436
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:181
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7957
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5825
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5503
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
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:7931
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17090
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2819
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:7038
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15459
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16963
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:1858
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:826
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15547
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:512
#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:10759
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17548
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1535
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11492
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17876
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3418
int index
Definition: struct_var.h:248
SCIP_Real constant
Definition: struct_var.h:177
unsigned int domchgtype
Definition: struct_var.h:142
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6087
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1455
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17007
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16358
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13859
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1911
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15224
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16941
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6227
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:271
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11305
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:667
SCIP_HOLECHG * holechgs
Definition: struct_var.h:134
SCIP_Real obj
Definition: struct_var.h:203
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17170
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:5435
SCIP_Real relaxsol
Definition: struct_var.h:210
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:1535
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:896
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6151
int conflictlbcount
Definition: struct_var.h:264
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13477
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:5825
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16306
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17696
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12555
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:422
SCIP_VAR ** vars
Definition: struct_var.h:186
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:194
real eps
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:207
int branchpriority
Definition: struct_var.h:259
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15702
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17684
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17330
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:593
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:1299
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:2271
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:196
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11485
SCIP_VAR * var
Definition: struct_var.h:178
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12488
int nrootboundchgs
Definition: struct_stat.h:205
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:151
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6047
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:7256
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:166
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17160
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1123
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3240
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15408
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:500
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:8963
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12627
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17776
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1414
SCIP_Real conflictrelaxedub
Definition: struct_var.h:216
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7347
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18099
unsigned int inferboundtype
Definition: struct_var.h:116
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:550
union SCIP_Var::@13 data
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:7680
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17354
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5993
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11704
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12372
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:268
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, SCIP_VARTYPE vartype)
Definition: var.c:5925
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13298
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4365
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10985
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:436
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:12951
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:704
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:246
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:215
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16771
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11175
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13957
SCIP_AGGREGATE aggregate
Definition: struct_var.h:225
SCIP_Real lazylb
Definition: struct_var.h:217
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:450
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16683
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:7294
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:1799
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16795
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7202
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17374
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:7514
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4349
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:525
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3303
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:12947
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16667
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14122
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17290
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1258
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:237
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:16300
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:14407
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:379
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:906
SCIP_Longint lpcount
Definition: struct_stat.h:174
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17886
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:623
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:5976
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11390
int lbchginfossize
Definition: struct_var.h:260
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15312
unsigned int varstatus
Definition: struct_var.h:274
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2774
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17310
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12347
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:680
SCIP_Real bestrootlpobjval
Definition: struct_var.h:209
SCIP_VARDATA * vardata
Definition: struct_var.h:234
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6164
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11420
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14006
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16142
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:212
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10384
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10655
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition: var.c:3056
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3426
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:273
SCIP_HOLECHG * holechgs
Definition: struct_var.h:144
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17610
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:6721
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:113
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1826
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17101
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16650
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16730
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:4872
SCIP_VAR * transvar
Definition: struct_var.h:170
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:155
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6529
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:97
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1908
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:541
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:662
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11471
unsigned int initial
Definition: struct_var.h:268
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13679
SCIP_NEGATE negate
Definition: struct_var.h:227
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4291
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:78
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:7347
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13344
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:165
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16627
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3269
#define REALABS(x)
Definition: def.h:181
int nparentvars
Definition: struct_var.h:255
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17718
SCIP_Real unchangedobj
Definition: struct_var.h:204
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:3627
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17364
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:9709
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14748
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
internal methods for global SCIP settings
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17214
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14226
#define SCIP_CALL(x)
Definition: def.h:358
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18085
SCIP_VBOUNDS * vubs
Definition: struct_var.h:238
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17482
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6439
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17568
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:14927
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17148
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2346
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14053
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:9428
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5618
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3277
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15659
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17600
Definition: grphload.c:88
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18074
int closestvubidx
Definition: struct_var.h:267
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14141
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:460
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5975
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11119
SCIP_Real vsidsweight
Definition: struct_stat.h:120
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:7806
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:267
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17996
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14795
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2895
unsigned int branchdirection
Definition: struct_var.h:276
int ubchginfossize
Definition: struct_var.h:262
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1578
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6395
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:268
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:323
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13329
int var_probindex
Definition: struct_lp.h:169
int nlocksdown[NLOCKTYPES]
Definition: struct_var.h:257
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6261
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:453
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16859
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:5949
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11049
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:5098
#define SCIP_UNKNOWN
Definition: def.h:178
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6098
public data structures and miscellaneous methods
unsigned int vartype
Definition: struct_var.h:273
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17654
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:457
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:15095
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:6396
SCIP_VAR * var
Definition: struct_var.h:90
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:88
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16707
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:8701
#define SCIP_Bool
Definition: def.h:69
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2762
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:444
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16647
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17986
unsigned int deletable
Definition: struct_var.h:270
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16431
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15504
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17069
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5843
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6196
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12753
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17731
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17516
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:715
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16023
SCIP_Bool divingobjchg
Definition: struct_lp.h:366
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17622
SCIP_MULTAGGR multaggr
Definition: struct_var.h:226
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8047
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:455
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:616
unsigned int deleted
Definition: struct_var.h:271
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3324
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16750
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3694
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3308
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10354
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3285
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:554
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16637
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11428
#define MIN(x, y)
Definition: def.h:216
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3355
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16685
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17202
public methods for LP management
unsigned int removable
Definition: struct_var.h:269
#define SCIPsetDebugMsg
Definition: set.h:1940
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2560
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8340
unsigned int redundant
Definition: struct_var.h:95
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17192
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10882
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17936
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13264
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17079
int closestvlbidx
Definition: struct_var.h:266
#define EPSLE(x, y, eps)
Definition: def.h:184
int nuses
Definition: struct_var.h:256
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15604
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:10668
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:10921
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:123
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:158
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17058
int probindex
Definition: struct_var.h:249
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:8453
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:2086
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13405
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17112
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:615
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17668
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12260
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6373
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:2350
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1494
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:14667
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:9220
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:139
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3739
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3314
SCIP * scip
Definition: struct_var.h:201
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:241
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12675
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15890
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2245
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18053
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:931
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15946
int conflictubcount
Definition: struct_var.h:265
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3253
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11955
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2198
SCIP_DOM locdom
Definition: struct_var.h:220
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17764
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:9501
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16002
#define SCIP_REAL_MAX
Definition: def.h:158
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6683
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:246
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2832
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:405
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:118
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:654
datastructures for storing and manipulating the main problem
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:13751
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3491
SCIP_Real newbound
Definition: struct_var.h:84
#define SCIP_REAL_MIN
Definition: def.h:159
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3532
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:235
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:413
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17639
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2588
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6518
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:153
SCIP_VAR ** b
Definition: circlepacking.c:56
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:7228
#define MAX(x, y)
Definition: def.h:215
#define SCIP_DEFAULT_INFINITY
Definition: def.h:162
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1201
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3295
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:94
SCIP_HOLELIST * next
Definition: struct_var.h:52
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6184
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:628
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:441
unsigned int boundtype
Definition: struct_var.h:115
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1918
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:726
static const SCIP_Real scalars[]
Definition: lp.c:5650
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:5264
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8357
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16677
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3457
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:2021
SCIP_Real lazyub
Definition: struct_var.h:218
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17976
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1759
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:135
unsigned int redundant
Definition: struct_var.h:117
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
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:3796
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:184
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:14341
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11477
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13198
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:206
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3427
SCIP_VAR * a
Definition: circlepacking.c:57
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:16806
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:8992
SCIP_Real * scalars
Definition: struct_var.h:185
SCIP_IMPLICS * implics
Definition: struct_var.h:239
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16697
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6029
datastructures for problem variables
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:102
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:353
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16849
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8939
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:150
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:9121
#define SCIP_Real
Definition: def.h:157
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:113
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2661
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
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15179
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11764
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18006
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6472
int parentvarssize
Definition: struct_var.h:254
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:240
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16817
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2355
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12048
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14101
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17809
#define SCIP_INVALID
Definition: def.h:177
internal methods for constraints and constraint handlers
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition: event.c:714
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:16740
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11684
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:2477
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2227
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17590
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:572
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:444
SCIP_Real branchfactor
Definition: struct_var.h:205
unsigned int donotmultaggr
Definition: struct_var.h:272
#define SCIP_Longint
Definition: def.h:142
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17456
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18018
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6672
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13544
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17027
SCIP_Real nlpsol
Definition: struct_var.h:211
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:167
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2536
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15745
SCIP_Real lb
Definition: struct_var.h:161
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6417
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:8830
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16895
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8208
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2801
SCIP_DOM glbdom
Definition: struct_var.h:219
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5835
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:641
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2847
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
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:6434
SCIP_Bool collectvarhistory
Definition: struct_stat.h:263
SCIP_VAR * negatedvar
Definition: struct_var.h:236
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16997
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3389
SCIP_Real newbound
Definition: struct_var.h:109
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17410
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3333
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8401
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15876
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6244
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16872
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6504
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:440
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17420
unsigned int delglobalstructs
Definition: struct_var.h:278
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6694
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17966
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:17851
SCIP_Real rootsol
Definition: struct_var.h:206
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2476
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2973
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13977
SCIP_HISTORY * history
Definition: struct_var.h:244
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16833
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15357
int nrootintfixingsrun
Definition: struct_stat.h:208
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:426
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12133
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
#define SCIP_CALL_ABORT(x)
Definition: def.h:337
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17796
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3312
SCIP_ORIGINAL original
Definition: struct_var.h:223
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3889
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17047
#define SCIP_ALLOC(x)
Definition: def.h:369
#define SCIPABORT()
Definition: def.h:330
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16921
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:639
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:56
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8142
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8690
unsigned int applied
Definition: struct_var.h:94
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16951
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:63
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10844
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:446
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5879
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16760
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16792
SCIP_COL * col
Definition: struct_var.h:224
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5702
SCIP_Real left
Definition: struct_var.h:44
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8942
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
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3330
#define EPSZ(x, eps)
Definition: def.h:187
#define ABS(x)
Definition: def.h:211
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:441
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11238
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3319
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:919
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6483
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14172
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17017
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:242
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14476
public methods for propagators
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1500
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16885
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:5547
SCIP_Real scalar
Definition: struct_var.h:176
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16987
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17956
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10904