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-2018 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  *infeasible = FALSE;
4614  *aggregated = FALSE;
4615 
4616  /* get active problem variable of aggregation variable */
4617  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4618 
4619  /* aggregation is a fixing, if the scalar is zero */
4620  if( SCIPsetIsZero(set, scalar) )
4621  {
4622  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4623  cliquetable, constant, infeasible, aggregated) );
4624  return SCIP_OKAY;
4625  }
4626 
4627  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4628  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4629  return SCIP_OKAY;
4630 
4631  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4632  * should be changed in the future
4633  */
4634  if( SCIPvarGetHolelistGlobal(var) != NULL )
4635  return SCIP_OKAY;
4636 
4637  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4638  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4639  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4640 
4641  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4642  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4643 
4644  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4645  if( var == aggvar )
4646  {
4647  if( SCIPsetIsEQ(set, scalar, 1.0) )
4648  *infeasible = !SCIPsetIsZero(set, constant);
4649  else
4650  {
4651  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4652  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4653  }
4654  return SCIP_OKAY;
4655  }
4656 
4657  /* tighten the bounds of aggregated and aggregation variable */
4658  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4659  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4660  if( *infeasible || fixed )
4661  {
4662  *aggregated = fixed;
4663  return SCIP_OKAY;
4664  }
4665 
4666  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4667  * aggregated variable
4668  */
4669  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4670  assert(var->cliquelist == NULL);
4671 
4672  /* set the aggregated variable's objective value to 0.0 */
4673  obj = var->obj;
4674  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4675 
4676  /* unlock all locks */
4677  for( i = 0; i < NLOCKTYPES; i++ )
4678  {
4679  nlocksdown[i] = var->nlocksdown[i];
4680  nlocksup[i] = var->nlocksup[i];
4681 
4682  var->nlocksdown[i] = 0;
4683  var->nlocksup[i] = 0;
4684  }
4685 
4686  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4687  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4688  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4689  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4690  {
4691  /* link both variables as negation pair */
4692  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4693  var->data.negate.constant = 1.0;
4694  var->negatedvar = aggvar;
4695  aggvar->negatedvar = var;
4696 
4697  /* copy doNotMultiaggr status */
4698  aggvar->donotmultaggr |= var->donotmultaggr;
4699 
4700  /* mark both variables to be non-deletable */
4702  SCIPvarMarkNotDeletable(aggvar);
4703  }
4704  else
4705  {
4706  /* convert variable into aggregated variable */
4707  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4708  var->data.aggregate.var = aggvar;
4709  var->data.aggregate.scalar = scalar;
4710  var->data.aggregate.constant = constant;
4711 
4712  /* copy doNotMultiaggr status */
4713  aggvar->donotmultaggr |= var->donotmultaggr;
4714 
4715  /* mark both variables to be non-deletable */
4717  SCIPvarMarkNotDeletable(aggvar);
4718  }
4719 
4720  /* make aggregated variable a parent of the aggregation variable */
4721  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4722 
4723  /* relock the variable, thus increasing the locks of the aggregation variable */
4724  for( i = 0; i < NLOCKTYPES; i++ )
4725  {
4726  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4727  }
4728 
4729  /* move the variable bounds to the aggregation variable:
4730  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4731  * - free the variable bounds data structures
4732  */
4733  if( var->vlbs != NULL )
4734  {
4735  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4736  vars = SCIPvboundsGetVars(var->vlbs);
4737  coefs = SCIPvboundsGetCoefs(var->vlbs);
4738  constants = SCIPvboundsGetConstants(var->vlbs);
4739  for( i = 0; i < nvbds && !(*infeasible); ++i )
4740  {
4741  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4742  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4743  }
4744  }
4745  if( var->vubs != NULL )
4746  {
4747  nvbds = SCIPvboundsGetNVbds(var->vubs);
4748  vars = SCIPvboundsGetVars(var->vubs);
4749  coefs = SCIPvboundsGetCoefs(var->vubs);
4750  constants = SCIPvboundsGetConstants(var->vubs);
4751  for( i = 0; i < nvbds && !(*infeasible); ++i )
4752  {
4753  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4754  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4755  }
4756  }
4757  SCIPvboundsFree(&var->vlbs, blkmem);
4758  SCIPvboundsFree(&var->vubs, blkmem);
4759 
4760  /* move the implications to the aggregation variable:
4761  * - add all implications again to the variable, thus adding it to the aggregation variable
4762  * - free the implications data structures
4763  */
4764  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4765  {
4766  assert(SCIPvarIsBinary(var));
4767  for( i = 0; i < 2; ++i )
4768  {
4769  SCIP_VAR** implvars;
4770  SCIP_BOUNDTYPE* impltypes;
4771  SCIP_Real* implbounds;
4772  int nimpls;
4773 
4774  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4775  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4776  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4777  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4778 
4779  for( j = 0; j < nimpls && !(*infeasible); ++j )
4780  {
4781  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4782  * implication to the aggregated variable?
4783  */
4784  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4785  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4786  NULL) );
4787  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4788  }
4789  }
4790  }
4791  SCIPimplicsFree(&var->implics, blkmem);
4792 
4793  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4794  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4795  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4796  SCIPhistoryReset(var->history);
4798 
4799  /* update flags of aggregation variable */
4800  aggvar->removable &= var->removable;
4801 
4802  /* update branching factors and priorities of both variables to be the maximum of both variables */
4803  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4804  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4805  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4806  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4807  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4808  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4809 
4810  /* update branching direction of both variables to agree to a single direction */
4811  if( scalar >= 0.0 )
4812  {
4814  {
4816  }
4817  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4818  {
4820  }
4821  else if( var->branchdirection != aggvar->branchdirection )
4822  {
4824  }
4825  }
4826  else
4827  {
4829  {
4831  }
4832  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4833  {
4835  }
4836  else if( var->branchdirection != aggvar->branchdirection )
4837  {
4839  }
4840  }
4841 
4842  if( var->probindex != -1 )
4843  {
4844  /* inform problem about the variable's status change */
4845  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4846  }
4847 
4848  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4849  * variable and the problem's objective offset
4850  */
4851  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4852 
4853  /* issue VARFIXED event */
4854  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4855 
4856  *aggregated = TRUE;
4857 
4858  return SCIP_OKAY;
4859 }
4860 
4861 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4862  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4863  *
4864  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4865  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4866  */
4867 static
4869  SCIP_SET* set, /**< global SCIP settings */
4870  BMS_BLKMEM* blkmem, /**< block memory */
4871  SCIP_STAT* stat, /**< problem statistics */
4872  SCIP_PROB* transprob, /**< tranformed problem data */
4873  SCIP_PROB* origprob, /**< original problem data */
4874  SCIP_PRIMAL* primal, /**< primal data */
4875  SCIP_TREE* tree, /**< branch and bound tree */
4876  SCIP_REOPT* reopt, /**< reoptimization data structure */
4877  SCIP_LP* lp, /**< current LP data */
4878  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4879  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4880  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4881  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4882  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4883  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4884  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4885  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4886  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4887  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4888  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4889  )
4890 {
4891  SCIP_VAR* aggvar;
4892  char aggvarname[SCIP_MAXSTRLEN];
4893  SCIP_Longint scalarxn = 0;
4894  SCIP_Longint scalarxd = 0;
4895  SCIP_Longint scalaryn = 0;
4896  SCIP_Longint scalaryd = 0;
4897  SCIP_Longint a;
4898  SCIP_Longint b;
4899  SCIP_Longint c;
4900  SCIP_Longint scm;
4901  SCIP_Longint gcd;
4902  SCIP_Longint currentclass;
4903  SCIP_Longint classstep;
4904  SCIP_Longint xsol;
4905  SCIP_Longint ysol;
4906  SCIP_Bool success;
4907  SCIP_VARTYPE vartype;
4908 
4909 #define MAXDNOM 1000000LL
4910 
4911  assert(set != NULL);
4912  assert(blkmem != NULL);
4913  assert(stat != NULL);
4914  assert(transprob != NULL);
4915  assert(origprob != NULL);
4916  assert(tree != NULL);
4917  assert(lp != NULL);
4918  assert(cliquetable != NULL);
4919  assert(branchcand != NULL);
4920  assert(eventqueue != NULL);
4921  assert(varx != NULL);
4922  assert(vary != NULL);
4923  assert(varx != vary);
4924  assert(infeasible != NULL);
4925  assert(aggregated != NULL);
4926  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4927  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4929  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4931  assert(!SCIPsetIsZero(set, scalarx));
4932  assert(!SCIPsetIsZero(set, scalary));
4933 
4934  *infeasible = FALSE;
4935  *aggregated = FALSE;
4936 
4937  /* get rational representation of coefficients */
4938  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4939  if( success )
4940  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4941  if( !success )
4942  return SCIP_OKAY;
4943  assert(scalarxd >= 1);
4944  assert(scalaryd >= 1);
4945 
4946  /* multiply equality with smallest common denominator */
4947  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4948  a = (scm/scalarxd)*scalarxn;
4949  b = (scm/scalaryd)*scalaryn;
4950  rhs *= scm;
4951 
4952  /* divide equality by the greatest common divisor of a and b */
4953  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4954  a /= gcd;
4955  b /= gcd;
4956  rhs /= gcd;
4957  assert(a != 0);
4958  assert(b != 0);
4959 
4960  /* check, if right hand side is integral */
4961  if( !SCIPsetIsFeasIntegral(set, rhs) )
4962  {
4963  *infeasible = TRUE;
4964  return SCIP_OKAY;
4965  }
4966  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4967 
4968  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
4969  return SCIP_OKAY;
4970 
4971  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4972  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4973  {
4974  /* aggregate x = - b/a*y + c/a */
4975  /*lint --e{653}*/
4976  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4977  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4978  assert(*aggregated);
4979  return SCIP_OKAY;
4980  }
4981  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4982  {
4983  /* aggregate y = - a/b*x + c/b */
4984  /*lint --e{653}*/
4985  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4986  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4987  assert(*aggregated);
4988  return SCIP_OKAY;
4989  }
4990 
4991  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4992  * common divisor. Let (x',y') be a solution of the equality
4993  * a*x + b*y == c -> a*x == c - b*y
4994  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4995  */
4996 
4997  /* find initial solution (x',y'):
4998  * - find y' such that c - b*y' is a multiple of a
4999  * - start in equivalence class c%a
5000  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5001  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5002  * - 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
5003  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5004  *
5005  * Algorithm works for a > 0 only.
5006  */
5007  if( a < 0 )
5008  {
5009  a = -a;
5010  b = -b;
5011  c = -c;
5012  }
5013  assert(0 <= a);
5014 
5015  /* search upwards from ysol = 0 */
5016  ysol = 0;
5017  currentclass = c%a;
5018  if( currentclass < 0 )
5019  currentclass += a;
5020  assert(0 <= currentclass && currentclass < a);
5021 
5022  classstep = (-b)%a;
5023 
5024  if( classstep < 0 )
5025  classstep += a;
5026  assert(0 <= classstep && classstep < a);
5027 
5028  while( currentclass != 0 )
5029  {
5030  assert(0 <= currentclass && currentclass < a);
5031  currentclass += classstep;
5032  if( currentclass >= a )
5033  currentclass -= a;
5034  ysol++;
5035  }
5036  assert(ysol < a);
5037  assert(((c - b*ysol)%a) == 0);
5038 
5039  xsol = (c - b*ysol)/a;
5040 
5041  /* determine variable type for new artificial variable:
5042  *
5043  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5044  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5045  * integral type
5046  */
5049 
5050  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5051  * - create new integer variable z with infinite bounds
5052  * - aggregate variable x = -b*z + x'
5053  * - aggregate variable y = a*z + y'
5054  * - the bounds of z are calculated automatically during aggregation
5055  */
5056  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5057  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5058  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5060  NULL, NULL, NULL, NULL, NULL) );
5061 
5062  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5063 
5064  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5065  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5066  assert(*aggregated || *infeasible);
5067 
5068  if( !(*infeasible) )
5069  {
5070  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5071  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5072  assert(*aggregated || *infeasible);
5073  }
5074 
5075  /* release z */
5076  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5077 
5078  return SCIP_OKAY;
5079 }
5080 
5081 /** performs second step of SCIPaggregateVars():
5082  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5083  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5084  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5085  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5086  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5087  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5088  *
5089  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5090  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5091  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5092  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5093  */
5095  SCIP_SET* set, /**< global SCIP settings */
5096  BMS_BLKMEM* blkmem, /**< block memory */
5097  SCIP_STAT* stat, /**< problem statistics */
5098  SCIP_PROB* transprob, /**< tranformed problem data */
5099  SCIP_PROB* origprob, /**< original problem data */
5100  SCIP_PRIMAL* primal, /**< primal data */
5101  SCIP_TREE* tree, /**< branch and bound tree */
5102  SCIP_REOPT* reopt, /**< reoptimization data structure */
5103  SCIP_LP* lp, /**< current LP data */
5104  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5105  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5106  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5107  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5108  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5109  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5110  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5111  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5112  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5113  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5114  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5115  )
5116 {
5117  SCIP_Bool easyaggr;
5118  SCIP_Real maxscalar;
5119  SCIP_Real absquot;
5120 
5121  assert(set != NULL);
5122  assert(blkmem != NULL);
5123  assert(stat != NULL);
5124  assert(transprob != NULL);
5125  assert(origprob != NULL);
5126  assert(tree != NULL);
5127  assert(lp != NULL);
5128  assert(cliquetable != NULL);
5129  assert(branchcand != NULL);
5130  assert(eventqueue != NULL);
5131  assert(varx != NULL);
5132  assert(vary != NULL);
5133  assert(varx != vary);
5134  assert(infeasible != NULL);
5135  assert(aggregated != NULL);
5136  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5137  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5138  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5139  assert(!SCIPsetIsZero(set, scalarx));
5140  assert(!SCIPsetIsZero(set, scalary));
5141 
5142  *infeasible = FALSE;
5143  *aggregated = FALSE;
5144 
5145  absquot = REALABS(scalarx / scalary);
5146  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5147  maxscalar = MAX(maxscalar, 1.0);
5148 
5149  if( absquot > maxscalar || absquot < 1 / maxscalar )
5150  return SCIP_OKAY;
5151 
5152  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5153  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5154  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5155  {
5156  SCIP_VAR* var;
5157  SCIP_Real scalar;
5158 
5159  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5160  var = vary;
5161  vary = varx;
5162  varx = var;
5163  scalar = scalary;
5164  scalary = scalarx;
5165  scalarx = scalar;
5166  }
5167 
5168  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5169  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5170  return SCIP_OKAY;
5171 
5172  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5173 
5174  /* figure out, which variable should be aggregated */
5175  easyaggr = FALSE;
5176 
5177  /* check if it is an easy aggregation that means:
5178  *
5179  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5180  */
5181  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5182  {
5184  {
5185  easyaggr = TRUE;
5186  }
5187  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5188  {
5189  easyaggr = TRUE;
5190  }
5191  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5192  {
5193  /* we have an easy aggregation if we flip the variables x and y */
5194  SCIP_VAR* var;
5195  SCIP_Real scalar;
5196 
5197  /* switch the variables, such that varx is the aggregated variable */
5198  var = vary;
5199  vary = varx;
5200  varx = var;
5201  scalar = scalary;
5202  scalary = scalarx;
5203  scalarx = scalar;
5204  easyaggr = TRUE;
5205  }
5206  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5207  {
5208  /* the aggregation is still easy if both variables are continuous */
5209  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5210  easyaggr = TRUE;
5211  }
5212  }
5213 
5214  /* did we find an "easy" aggregation? */
5215  if( easyaggr )
5216  {
5217  SCIP_Real scalar;
5218  SCIP_Real constant;
5219 
5220  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5221 
5222  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5223  scalar = -scalary/scalarx;
5224  constant = rhs/scalarx;
5225 
5226  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5227  return SCIP_OKAY;
5228 
5229  /* check aggregation for integer feasibility */
5232  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5233  {
5234  *infeasible = TRUE;
5235  return SCIP_OKAY;
5236  }
5237 
5238  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5239  * since then we would loose the corresponding divisibility property
5240  */
5241  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5242 
5243  /* aggregate the variable */
5244  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5245  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5246  assert(*aggregated || *infeasible);
5247  }
5250  {
5251  /* the variables are both integral: we have to try to find an integer aggregation */
5252  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5253  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5254  }
5255 
5256  return SCIP_OKAY;
5257 }
5258 
5259 /** converts variable into multi-aggregated variable */
5261  SCIP_VAR* var, /**< problem variable */
5262  BMS_BLKMEM* blkmem, /**< block memory */
5263  SCIP_SET* set, /**< global SCIP settings */
5264  SCIP_STAT* stat, /**< problem statistics */
5265  SCIP_PROB* transprob, /**< tranformed problem data */
5266  SCIP_PROB* origprob, /**< original problem data */
5267  SCIP_PRIMAL* primal, /**< primal data */
5268  SCIP_TREE* tree, /**< branch and bound tree */
5269  SCIP_REOPT* reopt, /**< reoptimization data structure */
5270  SCIP_LP* lp, /**< current LP data */
5271  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5272  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5273  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5274  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5275  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5276  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5277  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5278  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5279  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5280  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5281  )
5282 {
5283  SCIP_VAR** tmpvars;
5284  SCIP_Real* tmpscalars;
5285  SCIP_Real obj;
5286  SCIP_Real branchfactor;
5287  int branchpriority;
5288  SCIP_BRANCHDIR branchdirection;
5289  int nlocksdown[NLOCKTYPES];
5290  int nlocksup[NLOCKTYPES];
5291  int v;
5292  SCIP_Real tmpconstant;
5293  SCIP_Real tmpscalar;
5294  int ntmpvars;
5295  int tmpvarssize;
5296  int tmprequiredsize;
5297  int i;
5298 
5299  assert(var != NULL);
5300  assert(var->scip == set->scip);
5301  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5302  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5303  assert(naggvars == 0 || aggvars != NULL);
5304  assert(naggvars == 0 || scalars != NULL);
5305  assert(infeasible != NULL);
5306  assert(aggregated != NULL);
5307 
5308  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5309 
5310  *infeasible = FALSE;
5311  *aggregated = FALSE;
5312 
5313  switch( SCIPvarGetStatus(var) )
5314  {
5316  if( var->data.original.transvar == NULL )
5317  {
5318  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5319  return SCIP_INVALIDDATA;
5320  }
5321  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5322  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5323  break;
5324 
5325  case SCIP_VARSTATUS_LOOSE:
5326  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5327 
5328  /* check if we would create a self-reference */
5329  ntmpvars = naggvars;
5330  tmpvarssize = naggvars;
5331  tmpconstant = constant;
5332  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5333  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5334 
5335  /* get all active variables for multi-aggregation */
5336  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5337  if( tmprequiredsize > tmpvarssize )
5338  {
5339  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5340  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5341  tmpvarssize = tmprequiredsize;
5342  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5343  assert( tmprequiredsize <= tmpvarssize );
5344  }
5345 
5346  tmpscalar = 0.0;
5347 
5348  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5349  * possible multi-aggregated variable
5350  */
5351  for( v = ntmpvars - 1; v >= 0; --v )
5352  {
5353  assert(tmpvars[v] != NULL);
5354  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5355 
5356  if( tmpvars[v]->index == var->index )
5357  {
5358  tmpscalar += tmpscalars[v];
5359  tmpvars[v] = tmpvars[ntmpvars - 1];
5360  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5361  --ntmpvars;
5362  }
5363  }
5364 
5365  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5366  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5367  {
5368  if( ntmpvars == 0 )
5369  {
5370  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5371  {
5372  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5373  goto TERMINATE;
5374  }
5375  else /* 0 = c and c != 0 */
5376  {
5377  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5378  *infeasible = TRUE;
5379  goto TERMINATE;
5380  }
5381  }
5382  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5383  {
5384  assert(tmpscalars[0] != 0.0);
5385  assert(tmpvars[0] != NULL);
5386 
5387  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5388  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5389  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5390  goto TERMINATE;
5391  }
5392  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 */
5393  {
5394  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5395 
5396  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5397  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5398 
5399  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5400  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5401  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5402 
5403  goto TERMINATE;
5404  }
5405  else
5406  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5407  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5408  */
5409  goto TERMINATE;
5410  }
5411  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5412  else if( !SCIPsetIsZero(set, tmpscalar) )
5413  {
5414  tmpscalar = 1 - tmpscalar;
5415  tmpconstant /= tmpscalar;
5416  for( v = ntmpvars - 1; v >= 0; --v )
5417  tmpscalars[v] /= tmpscalar;
5418  }
5419 
5420  /* check, if we are in one of the simple cases */
5421  if( ntmpvars == 0 )
5422  {
5423  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5424  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5425  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5426  goto TERMINATE;
5427  }
5428 
5429  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5430  if( ntmpvars == 1 )
5431  {
5432  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5433  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5434 
5435  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5436  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5437  infeasible, aggregated) );
5438 
5439  goto TERMINATE;
5440  }
5441 
5442  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5443  * empty hole list; this should be changed in the future */
5444  if( SCIPvarGetHolelistGlobal(var) != NULL )
5445  goto TERMINATE;
5446 
5447  /* if the variable is not allowed to be multi-aggregated */
5448  if( SCIPvarDoNotMultaggr(var) )
5449  {
5450  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5451  goto TERMINATE;
5452  }
5453 
5454  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5455  * variable bound variable of another variable), we have to remove it from the other variables implications or
5456  * variable bounds
5457  */
5458  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5459  assert(var->vlbs == NULL);
5460  assert(var->vubs == NULL);
5461  assert(var->implics == NULL);
5462  assert(var->cliquelist == NULL);
5463 
5464  /* set the aggregated variable's objective value to 0.0 */
5465  obj = var->obj;
5466  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5467 
5468  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5469  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5470  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5471  * objective of this variable is set to zero
5472  */
5473  SCIPlpDecNLoosevars(lp);
5474 
5475  /* unlock all rounding locks */
5476  for( i = 0; i < NLOCKTYPES; i++ )
5477  {
5478  nlocksdown[i] = var->nlocksdown[i];
5479  nlocksup[i] = var->nlocksup[i];
5480 
5481  var->nlocksdown[i] = 0;
5482  var->nlocksup[i] = 0;
5483  }
5484 
5485  /* convert variable into multi-aggregated variable */
5486  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5487  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5488  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5489  var->data.multaggr.constant = tmpconstant;
5490  var->data.multaggr.nvars = ntmpvars;
5491  var->data.multaggr.varssize = ntmpvars;
5492 
5493  /* mark variable to be non-deletable */
5495 
5496  /* relock the variable, thus increasing the locks of the aggregation variables */
5497  for( i = 0; i < NLOCKTYPES; i++ )
5498  {
5499  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5500  }
5501 
5502  /* update flags and branching factors and priorities of aggregation variables;
5503  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5504  */
5505  branchfactor = var->branchfactor;
5506  branchpriority = var->branchpriority;
5507  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5508 
5509  for( v = 0; v < ntmpvars; ++v )
5510  {
5511  assert(tmpvars[v] != NULL);
5512  tmpvars[v]->removable &= var->removable;
5513  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5514  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5515 
5516  /* mark variable to be non-deletable */
5517  SCIPvarMarkNotDeletable(tmpvars[v]);
5518  }
5519  for( v = 0; v < ntmpvars; ++v )
5520  {
5521  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5522  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5523  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5524  {
5525  if( tmpscalars[v] >= 0.0 )
5526  {
5527  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5528  }
5529  else
5530  {
5531  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5532  }
5533  }
5534  }
5535  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5536  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5537 
5538  if( var->probindex != -1 )
5539  {
5540  /* inform problem about the variable's status change */
5541  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5542  }
5543 
5544  /* issue VARFIXED event */
5545  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5546 
5547  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5548  * variables and the problem's objective offset
5549  */
5550  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5551 
5552  *aggregated = TRUE;
5553 
5554  TERMINATE:
5555  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5556  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5557 
5558  break;
5559 
5560  case SCIP_VARSTATUS_COLUMN:
5561  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5562  return SCIP_INVALIDDATA;
5563 
5564  case SCIP_VARSTATUS_FIXED:
5565  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5566  return SCIP_INVALIDDATA;
5567 
5569  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5570  return SCIP_INVALIDDATA;
5571 
5573  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5574  return SCIP_INVALIDDATA;
5575 
5577  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5578  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5579  */
5580  assert(SCIPsetIsZero(set, var->obj));
5581  assert(var->negatedvar != NULL);
5583  assert(var->negatedvar->negatedvar == var);
5584 
5585  /* switch the signs of the aggregation scalars */
5586  for( v = 0; v < naggvars; ++v )
5587  scalars[v] *= -1.0;
5588 
5589  /* perform the multi aggregation on the negation variable */
5590  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5591  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5592  var->data.negate.constant - constant, infeasible, aggregated) );
5593 
5594  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5595  for( v = 0; v < naggvars; ++v )
5596  scalars[v] *= -1.0;
5597  break;
5598 
5599  default:
5600  SCIPerrorMessage("unknown variable status\n");
5601  return SCIP_INVALIDDATA;
5602  }
5603 
5604  return SCIP_OKAY;
5605 }
5606 
5607 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5608  * or for original variables the same variable is returned
5609  */
5610 static
5612  SCIP_VAR* var /**< problem variable */
5613  )
5614 {
5615  SCIP_VAR* retvar;
5616 
5617  assert(var != NULL);
5618 
5619  retvar = var;
5620 
5621  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5622 
5623  while( TRUE ) /*lint !e716 */
5624  {
5625  assert(retvar != NULL);
5626 
5627  switch( SCIPvarGetStatus(retvar) )
5628  {
5630  case SCIP_VARSTATUS_LOOSE:
5631  case SCIP_VARSTATUS_COLUMN:
5632  case SCIP_VARSTATUS_FIXED:
5633  return retvar;
5634 
5636  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5637  if ( retvar->data.multaggr.nvars == 1 )
5638  retvar = retvar->data.multaggr.vars[0];
5639  else
5640  return retvar;
5641  break;
5642 
5644  retvar = retvar->data.aggregate.var;
5645  break;
5646 
5648  retvar = retvar->negatedvar;
5649  break;
5650 
5651  default:
5652  SCIPerrorMessage("unknown variable status\n");
5653  SCIPABORT();
5654  return NULL; /*lint !e527*/
5655  }
5656  }
5657 }
5658 
5659 /** returns whether variable is not allowed to be multi-aggregated */
5661  SCIP_VAR* var /**< problem variable */
5662  )
5663 {
5664  SCIP_VAR* retvar;
5665 
5666  assert(var != NULL);
5667 
5668  retvar = varGetActiveVar(var);
5669  assert(retvar != NULL);
5670 
5671  switch( SCIPvarGetStatus(retvar) )
5672  {
5674  case SCIP_VARSTATUS_LOOSE:
5675  case SCIP_VARSTATUS_COLUMN:
5676  case SCIP_VARSTATUS_FIXED:
5677  return retvar->donotmultaggr;
5678 
5680  return FALSE;
5681 
5684  default:
5685  SCIPerrorMessage("wrong variable status\n");
5686  SCIPABORT();
5687  return FALSE; /*lint !e527 */
5688  }
5689 }
5690 
5691 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5692  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5693  * negated variable is created
5694  */
5696  SCIP_VAR* var, /**< problem variable to negate */
5697  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5698  SCIP_SET* set, /**< global SCIP settings */
5699  SCIP_STAT* stat, /**< problem statistics */
5700  SCIP_VAR** negvar /**< pointer to store the negated variable */
5701  )
5702 {
5703  assert(var != NULL);
5704  assert(var->scip == set->scip);
5705  assert(negvar != NULL);
5706 
5707  /* check, if we already created the negated variable */
5708  if( var->negatedvar == NULL )
5709  {
5710  char negvarname[SCIP_MAXSTRLEN];
5711 
5712  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5713 
5714  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5715 
5716  /* negation is only possible for bounded variables */
5717  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5718  {
5719  SCIPerrorMessage("cannot negate unbounded variable\n");
5720  return SCIP_INVALIDDATA;
5721  }
5722 
5723  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5724 
5725  /* create negated variable */
5726  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5727  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5728  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5729  if( SCIPvarIsBinary(var) )
5730  (*negvar)->data.negate.constant = 1.0;
5731  else
5732  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5733 
5734  /* create event filter for transformed variable */
5735  if( SCIPvarIsTransformed(var) )
5736  {
5737  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5738  }
5739 
5740  /* set the bounds corresponding to the negation variable */
5741  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5742  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5743  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5744  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5745  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5746 
5747  /* link the variables together */
5748  var->negatedvar = *negvar;
5749  (*negvar)->negatedvar = var;
5750 
5751  /* mark both variables to be non-deletable */
5753  SCIPvarMarkNotDeletable(*negvar);
5754 
5755  /* copy the branch factor and priority, and use the negative preferred branching direction */
5756  (*negvar)->branchfactor = var->branchfactor;
5757  (*negvar)->branchpriority = var->branchpriority;
5758  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5759 
5760  /* copy doNotMultiaggr status */
5761  (*negvar)->donotmultaggr = var->donotmultaggr;
5762 
5763  /* copy lazy bounds (they have to be flipped) */
5764  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5765  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5766 
5767  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5768  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5769  assert((*negvar)->nuses == 1);
5770  }
5771  assert(var->negatedvar != NULL);
5772 
5773  /* return the negated variable */
5774  *negvar = var->negatedvar;
5775 
5776  /* exactly one variable of the negation pair has to be marked as negated variable */
5778 
5779  return SCIP_OKAY;
5780 }
5781 
5782 /** informs variable that its position in problem's vars array changed */
5783 static
5784 void varSetProbindex(
5785  SCIP_VAR* var, /**< problem variable */
5786  int probindex /**< new problem index of variable (-1 for removal) */
5787  )
5788 {
5789  assert(var != NULL);
5790  assert(probindex >= 0 || var->vlbs == NULL);
5791  assert(probindex >= 0 || var->vubs == NULL);
5792  assert(probindex >= 0 || var->implics == NULL);
5793 
5794  var->probindex = probindex;
5796  {
5797  assert(var->data.col != NULL);
5798  var->data.col->var_probindex = probindex;
5799  }
5800 }
5801 
5802 /** informs variable that its position in problem's vars array changed */
5803 void SCIPvarSetProbindex(
5804  SCIP_VAR* var, /**< problem variable */
5805  int probindex /**< new problem index of variable */
5806  )
5807 {
5808  assert(var != NULL);
5809  assert(probindex >= 0);
5810 
5811  varSetProbindex(var, probindex);
5812 }
5813 
5814 /** gives the variable a new name
5815  *
5816  * @note the old pointer is overwritten, which might result in a memory leakage
5817  */
5819  SCIP_VAR* var, /**< problem variable */
5820  const char* name /**< new name of variable */
5821  )
5822 {
5823  assert(var != NULL);
5824  assert(name != NULL);
5825 
5826  var->name = (char*)name;
5827 }
5828 
5829 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5830  * implication graph;
5831  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5832  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5833  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5834  * than removing the variables one by one, each time updating all lists of the other variables.
5835  */
5837  SCIP_VAR* var, /**< problem variable */
5838  BMS_BLKMEM* blkmem, /**< block memory buffer */
5839  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5840  SCIP_SET* set, /**< global SCIP settings */
5841  SCIP_Bool final /**< is this the final removal of all problem variables? */
5842  )
5843 {
5844  assert(SCIPvarGetProbindex(var) >= 0);
5845  assert(var->scip == set->scip);
5846 
5847  /* if the variable is active in the transformed problem, remove it from the implication graph */
5848  if( SCIPvarIsTransformed(var)
5850  {
5851  if( final )
5852  {
5853  /* just destroy the data structures */
5854  SCIPvboundsFree(&var->vlbs, blkmem);
5855  SCIPvboundsFree(&var->vubs, blkmem);
5856  SCIPimplicsFree(&var->implics, blkmem);
5857  }
5858  else
5859  {
5860  /* unlink the variable from all other variables' lists and free the data structures */
5861  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5862  }
5863  }
5864 
5865  /* mark the variable to be no longer a member of the problem */
5866  varSetProbindex(var, -1);
5867 
5868  return SCIP_OKAY;
5869 }
5870 
5871 /** marks the variable to be deleted from the problem */
5872 void SCIPvarMarkDeleted(
5873  SCIP_VAR* var /**< problem variable */
5874  )
5875 {
5876  assert(var != NULL);
5877  assert(var->probindex != -1);
5878 
5879  var->deleted = TRUE;
5880 }
5881 
5882 /** marks the variable to not to be multi-aggregated */
5884  SCIP_VAR* var /**< problem variable */
5885  )
5886 {
5887  SCIP_VAR* retvar;
5888 
5889  assert(var != NULL);
5890 
5891  retvar = varGetActiveVar(var);
5892  assert(retvar != NULL);
5893 
5894  switch( SCIPvarGetStatus(retvar) )
5895  {
5897  case SCIP_VARSTATUS_LOOSE:
5898  case SCIP_VARSTATUS_COLUMN:
5899  case SCIP_VARSTATUS_FIXED:
5900  retvar->donotmultaggr = TRUE;
5901  break;
5902 
5904  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5905  return SCIP_INVALIDDATA;
5906 
5909  default:
5910  SCIPerrorMessage("wrong variable status\n");
5911  return SCIP_INVALIDDATA;
5912  }
5913 
5914  return SCIP_OKAY;
5915 }
5916 
5917 /** changes type of variable; cannot be called, if var belongs to a problem */
5919  SCIP_VAR* var, /**< problem variable to change */
5920  SCIP_VARTYPE vartype /**< new type of variable */
5921  )
5922 {
5923  assert(var != NULL);
5924 
5925  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5926 
5927  if( var->probindex >= 0 )
5928  {
5929  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5930  return SCIP_INVALIDDATA;
5931  }
5932 
5933  var->vartype = vartype; /*lint !e641*/
5934  if( var->negatedvar != NULL )
5935  var->negatedvar->vartype = vartype; /*lint !e641*/
5936 
5937  return SCIP_OKAY;
5938 }
5939 
5940 /** appends OBJCHANGED event to the event queue */
5941 static
5943  SCIP_VAR* var, /**< problem variable to change */
5944  BMS_BLKMEM* blkmem, /**< block memory */
5945  SCIP_SET* set, /**< global SCIP settings */
5946  SCIP_PRIMAL* primal, /**< primal data */
5947  SCIP_LP* lp, /**< current LP data */
5948  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5949  SCIP_Real oldobj, /**< old objective value for variable */
5950  SCIP_Real newobj /**< new objective value for variable */
5951  )
5952 {
5953  SCIP_EVENT* event;
5954 
5955  assert(var != NULL);
5956  assert(var->scip == set->scip);
5957  assert(var->eventfilter != NULL);
5959  assert(SCIPvarIsTransformed(var));
5960  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5961 
5962  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5963  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5964 
5965  return SCIP_OKAY;
5966 }
5967 
5968 /** changes objective value of variable */
5970  SCIP_VAR* var, /**< variable to change */
5971  BMS_BLKMEM* blkmem, /**< block memory */
5972  SCIP_SET* set, /**< global SCIP settings */
5973  SCIP_PROB* prob, /**< problem data */
5974  SCIP_PRIMAL* primal, /**< primal data */
5975  SCIP_LP* lp, /**< current LP data */
5976  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5977  SCIP_Real newobj /**< new objective value for variable */
5978  )
5979 {
5980  SCIP_Real oldobj;
5981 
5982  assert(var != NULL);
5983  assert(set != NULL);
5984  assert(var->scip == set->scip);
5985 
5986  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5987 
5988  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5989  {
5990  switch( SCIPvarGetStatus(var) )
5991  {
5993  if( var->data.original.transvar != NULL )
5994  {
5995  assert(SCIPprobIsTransformed(prob));
5996 
5997  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
5998  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
5999  }
6000  else
6001  assert(set->stage == SCIP_STAGE_PROBLEM);
6002 
6003  var->obj = newobj;
6004  var->unchangedobj = newobj;
6005 
6006  break;
6007 
6008  case SCIP_VARSTATUS_LOOSE:
6009  case SCIP_VARSTATUS_COLUMN:
6010  oldobj = var->obj;
6011  var->obj = newobj;
6012 
6013  /* update unchanged objective value of variable */
6014  if( !lp->divingobjchg )
6015  var->unchangedobj = newobj;
6016 
6017  /* update the number of variables with non-zero objective coefficient;
6018  * we only want to do the update, if the variable is added to the problem;
6019  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6020  */
6021  if( SCIPvarIsActive(var) )
6022  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6023 
6024  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6025  break;
6026 
6027  case SCIP_VARSTATUS_FIXED:
6031  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6032  return SCIP_INVALIDDATA;
6033 
6034  default:
6035  SCIPerrorMessage("unknown variable status\n");
6036  return SCIP_INVALIDDATA;
6037  }
6038  }
6039 
6040  return SCIP_OKAY;
6041 }
6042 
6043 /** adds value to objective value of variable */
6045  SCIP_VAR* var, /**< variable to change */
6046  BMS_BLKMEM* blkmem, /**< block memory */
6047  SCIP_SET* set, /**< global SCIP settings */
6048  SCIP_STAT* stat, /**< problem statistics */
6049  SCIP_PROB* transprob, /**< transformed problem data */
6050  SCIP_PROB* origprob, /**< original problem data */
6051  SCIP_PRIMAL* primal, /**< primal data */
6052  SCIP_TREE* tree, /**< branch and bound tree */
6053  SCIP_REOPT* reopt, /**< reoptimization data structure */
6054  SCIP_LP* lp, /**< current LP data */
6055  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6056  SCIP_Real addobj /**< additional objective value for variable */
6057  )
6058 {
6059  assert(var != NULL);
6060  assert(set != NULL);
6061  assert(var->scip == set->scip);
6062  assert(set->stage < SCIP_STAGE_INITSOLVE);
6063 
6064  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6065 
6066  if( !SCIPsetIsZero(set, addobj) )
6067  {
6068  SCIP_Real oldobj;
6069  int i;
6070 
6071  switch( SCIPvarGetStatus(var) )
6072  {
6074  if( var->data.original.transvar != NULL )
6075  {
6076  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6077  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6078  }
6079  else
6080  assert(set->stage == SCIP_STAGE_PROBLEM);
6081 
6082  var->obj += addobj;
6083  var->unchangedobj += addobj;
6084  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6085 
6086  break;
6087 
6088  case SCIP_VARSTATUS_LOOSE:
6089  case SCIP_VARSTATUS_COLUMN:
6090  oldobj = var->obj;
6091  var->obj += addobj;
6092 
6093  /* update unchanged objective value of variable */
6094  if( !lp->divingobjchg )
6095  {
6096  var->unchangedobj += addobj;
6097  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6098  }
6099 
6100  /* update the number of variables with non-zero objective coefficient;
6101  * we only want to do the update, if the variable is added to the problem;
6102  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6103  */
6104  if( SCIPvarIsActive(var) )
6105  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6106 
6107  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6108  break;
6109 
6110  case SCIP_VARSTATUS_FIXED:
6111  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6112  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6113  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6114  break;
6115 
6117  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6118  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6119  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6120  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6121  lp, eventqueue, var->data.aggregate.scalar * addobj) );
6122  break;
6123 
6125  assert(!var->donotmultaggr);
6126  /* 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 */
6127  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6128  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6129  for( i = 0; i < var->data.multaggr.nvars; ++i )
6130  {
6131  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6132  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6133  }
6134  break;
6135 
6137  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6138  assert(var->negatedvar != NULL);
6140  assert(var->negatedvar->negatedvar == var);
6141  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6142  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6143  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6144  eventqueue, -addobj) );
6145  break;
6146 
6147  default:
6148  SCIPerrorMessage("unknown variable status\n");
6149  return SCIP_INVALIDDATA;
6150  }
6151  }
6152 
6153  return SCIP_OKAY;
6154 }
6155 
6156 /** changes objective value of variable in current dive */
6158  SCIP_VAR* var, /**< problem variable to change */
6159  SCIP_SET* set, /**< global SCIP settings */
6160  SCIP_LP* lp, /**< current LP data */
6161  SCIP_Real newobj /**< new objective value for variable */
6162  )
6163 {
6164  assert(var != NULL);
6165  assert(set != NULL);
6166  assert(var->scip == set->scip);
6167  assert(lp != NULL);
6168 
6169  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6170 
6171  if( SCIPsetIsZero(set, newobj) )
6172  newobj = 0.0;
6173 
6174  /* change objective value of attached variables */
6175  switch( SCIPvarGetStatus(var) )
6176  {
6178  assert(var->data.original.transvar != NULL);
6179  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6180  break;
6181 
6182  case SCIP_VARSTATUS_COLUMN:
6183  assert(var->data.col != NULL);
6184  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6185  break;
6186 
6187  case SCIP_VARSTATUS_LOOSE:
6188  case SCIP_VARSTATUS_FIXED:
6189  /* nothing to do here: only the constant shift in objective function would change */
6190  break;
6191 
6192  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6193  assert(var->data.aggregate.var != NULL);
6194  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6195  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6196  /* the constant can be ignored, because it would only affect the objective shift */
6197  break;
6198 
6200  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6201  return SCIP_INVALIDDATA;
6202 
6203  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6204  assert(var->negatedvar != NULL);
6206  assert(var->negatedvar->negatedvar == var);
6207  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6208  /* the offset can be ignored, because it would only affect the objective shift */
6209  break;
6210 
6211  default:
6212  SCIPerrorMessage("unknown variable status\n");
6213  return SCIP_INVALIDDATA;
6214  }
6215 
6216  return SCIP_OKAY;
6217 }
6218 
6219 /** adjust lower bound to integral value, if variable is integral */
6220 void SCIPvarAdjustLb(
6221  SCIP_VAR* var, /**< problem variable */
6222  SCIP_SET* set, /**< global SCIP settings */
6223  SCIP_Real* lb /**< pointer to lower bound to adjust */
6224  )
6225 {
6226  assert(var != NULL);
6227  assert(set != NULL);
6228  assert(var->scip == set->scip);
6229  assert(lb != NULL);
6230 
6231  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6232 
6233  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6234 }
6235 
6236 /** adjust upper bound to integral value, if variable is integral */
6237 void SCIPvarAdjustUb(
6238  SCIP_VAR* var, /**< problem variable */
6239  SCIP_SET* set, /**< global SCIP settings */
6240  SCIP_Real* ub /**< pointer to upper bound to adjust */
6241  )
6242 {
6243  assert(var != NULL);
6244  assert(set != NULL);
6245  assert(var->scip == set->scip);
6246  assert(ub != NULL);
6247 
6248  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6249 
6250  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6251 }
6252 
6253 /** adjust lower or upper bound to integral value, if variable is integral */
6254 void SCIPvarAdjustBd(
6255  SCIP_VAR* var, /**< problem variable */
6256  SCIP_SET* set, /**< global SCIP settings */
6257  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6258  SCIP_Real* bd /**< pointer to bound to adjust */
6259  )
6260 {
6261  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6262 
6263  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6264  SCIPvarAdjustLb(var, set, bd);
6265  else
6266  SCIPvarAdjustUb(var, set, bd);
6267 }
6268 
6269 /** changes lower bound of original variable in original problem */
6271  SCIP_VAR* var, /**< problem variable to change */
6272  SCIP_SET* set, /**< global SCIP settings */
6273  SCIP_Real newbound /**< new bound for variable */
6274  )
6275 {
6276  int i;
6277 
6278  assert(var != NULL);
6279  assert(!SCIPvarIsTransformed(var));
6281  assert(set != NULL);
6282  assert(var->scip == set->scip);
6283  assert(set->stage == SCIP_STAGE_PROBLEM);
6284 
6285  /* check that the bound is feasible */
6286  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6287  /* adjust bound to integral value if variable is of integral type */
6288  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6289 
6290  if( SCIPsetIsZero(set, newbound) )
6291  newbound = 0.0;
6292 
6293  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6295  {
6296  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6297  var->name, var->data.original.origdom.lb, newbound);
6298 
6299  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6300  return SCIP_OKAY;
6301 
6302  /* change the bound */
6303  var->data.original.origdom.lb = newbound;
6304  }
6305  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6306  {
6307  assert( var->negatedvar != NULL );
6308  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6309  }
6310 
6311  /* process parent variables */
6312  for( i = 0; i < var->nparentvars; ++i )
6313  {
6314  SCIP_VAR* parentvar;
6315 
6316  parentvar = var->parentvars[i];
6317  assert(parentvar != NULL);
6318  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6319  assert(parentvar->negatedvar == var);
6320  assert(var->negatedvar == parentvar);
6321 
6322  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6323  }
6324 
6325  return SCIP_OKAY;
6326 }
6327 
6328 /** changes upper bound of original variable in original problem */
6330  SCIP_VAR* var, /**< problem variable to change */
6331  SCIP_SET* set, /**< global SCIP settings */
6332  SCIP_Real newbound /**< new bound for variable */
6333  )
6334 {
6335  int i;
6336 
6337  assert(var != NULL);
6338  assert(!SCIPvarIsTransformed(var));
6340  assert(set != NULL);
6341  assert(var->scip == set->scip);
6342  assert(set->stage == SCIP_STAGE_PROBLEM);
6343 
6344  /* check that the bound is feasible */
6345  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6346  /* adjust bound to integral value if variable is of integral type */
6347  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6348 
6349  if( SCIPsetIsZero(set, newbound) )
6350  newbound = 0.0;
6351 
6352  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6354  {
6355  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6356  var->name, var->data.original.origdom.ub, newbound);
6357 
6358  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6359  return SCIP_OKAY;
6360 
6361  /* change the bound */
6362  var->data.original.origdom.ub = newbound;
6363  }
6364  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6365  {
6366  assert( var->negatedvar != NULL );
6367  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6368  }
6369 
6370  /* process parent variables */
6371  for( i = 0; i < var->nparentvars; ++i )
6372  {
6373  SCIP_VAR* parentvar;
6374 
6375  parentvar = var->parentvars[i];
6376  assert(parentvar != NULL);
6377  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6378  assert(parentvar->negatedvar == var);
6379  assert(var->negatedvar == parentvar);
6380 
6381  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6382  }
6383 
6384  return SCIP_OKAY;
6385 }
6386 
6387 /** appends GLBCHANGED event to the event queue */
6388 static
6390  SCIP_VAR* var, /**< problem variable to change */
6391  BMS_BLKMEM* blkmem, /**< block memory */
6392  SCIP_SET* set, /**< global SCIP settings */
6393  SCIP_LP* lp, /**< current LP data */
6394  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6395  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6396  SCIP_Real oldbound, /**< old lower bound for variable */
6397  SCIP_Real newbound /**< new lower bound for variable */
6398  )
6399 {
6400  assert(var != NULL);
6401  assert(var->eventfilter != NULL);
6402  assert(SCIPvarIsTransformed(var));
6403  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6404  assert(set != NULL);
6405  assert(var->scip == set->scip);
6406 
6407  /* check, if the variable is being tracked for bound changes
6408  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6409  */
6410  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6413  {
6414  SCIP_EVENT* event;
6415 
6416  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6417 
6418  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6419  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6420  }
6421 
6422  return SCIP_OKAY;
6423 }
6424 
6425 /** appends GUBCHANGED event to the event queue */
6426 static
6428  SCIP_VAR* var, /**< problem variable to change */
6429  BMS_BLKMEM* blkmem, /**< block memory */
6430  SCIP_SET* set, /**< global SCIP settings */
6431  SCIP_LP* lp, /**< current LP data */
6432  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6433  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6434  SCIP_Real oldbound, /**< old lower bound for variable */
6435  SCIP_Real newbound /**< new lower bound for variable */
6436  )
6437 {
6438  assert(var != NULL);
6439  assert(var->eventfilter != NULL);
6440  assert(SCIPvarIsTransformed(var));
6441  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6442  assert(set != NULL);
6443  assert(var->scip == set->scip);
6444 
6445  /* check, if the variable is being tracked for bound changes
6446  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6447  */
6448  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6451  {
6452  SCIP_EVENT* event;
6453 
6454  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6455 
6456  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6457  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6458  }
6459 
6460  return SCIP_OKAY;
6461 }
6462 
6463 /** appends GHOLEADDED event to the event queue */
6464 static
6466  SCIP_VAR* var, /**< problem variable to change */
6467  BMS_BLKMEM* blkmem, /**< block memory */
6468  SCIP_SET* set, /**< global SCIP settings */
6469  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6470  SCIP_Real left, /**< left bound of open interval in new hole */
6471  SCIP_Real right /**< right bound of open interval in new hole */
6472  )
6473 {
6474  assert(var != NULL);
6475  assert(var->eventfilter != NULL);
6476  assert(SCIPvarIsTransformed(var));
6477  assert(set != NULL);
6478  assert(var->scip == set->scip);
6479  assert(SCIPsetIsLT(set, left, right));
6480 
6481  /* check, if the variable is being tracked for bound changes */
6482  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6483  {
6484  SCIP_EVENT* event;
6485 
6486  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6487 
6488  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6489  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6490  }
6491 
6492  return SCIP_OKAY;
6493 }
6494 
6495 /** increases root bound change statistics after a global bound change */
6496 static
6497 void varIncRootboundchgs(
6498  SCIP_VAR* var, /**< problem variable to change */
6499  SCIP_SET* set, /**< global SCIP settings */
6500  SCIP_STAT* stat /**< problem statistics */
6501  )
6502 {
6503  assert(var != NULL);
6504  assert(set != NULL);
6505  assert(var->scip == set->scip);
6506  assert(stat != NULL);
6507 
6508  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6509  {
6510  stat->nrootboundchgs++;
6511  stat->nrootboundchgsrun++;
6512  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6513  {
6514  stat->nrootintfixings++;
6515  stat->nrootintfixingsrun++;
6516  }
6517  }
6518 }
6519 
6520 /* forward declaration, because both methods call each other recursively */
6521 
6522 /* performs the current change in upper bound, changes all parents accordingly */
6523 static
6525  SCIP_VAR* var, /**< problem variable to change */
6526  BMS_BLKMEM* blkmem, /**< block memory */
6527  SCIP_SET* set, /**< global SCIP settings */
6528  SCIP_STAT* stat, /**< problem statistics */
6529  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6530  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6531  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6532  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6533  SCIP_Real newbound /**< new bound for variable */
6534  );
6535 
6536 /** performs the current change in lower bound, changes all parents accordingly */
6537 static
6539  SCIP_VAR* var, /**< problem variable to change */
6540  BMS_BLKMEM* blkmem, /**< block memory */
6541  SCIP_SET* set, /**< global SCIP settings */
6542  SCIP_STAT* stat, /**< problem statistics */
6543  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6544  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6545  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6546  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6547  SCIP_Real newbound /**< new bound for variable */
6548  )
6549 {
6550  SCIP_VAR* parentvar;
6551  SCIP_Real oldbound;
6552  int i;
6553 
6554  assert(var != NULL);
6555  /* local domains can violate global bounds but not more than feasibility epsilon */
6556  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6557  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6558  assert(blkmem != NULL);
6559  assert(set != NULL);
6560  assert(var->scip == set->scip);
6561  assert(stat != NULL);
6562 
6563  /* adjust bound to integral value if variable is of integral type */
6564  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6565 
6566  /* check that the bound is feasible */
6567  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6568  {
6569  /* due to numerics we only want to be feasible in feasibility tolerance */
6570  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6571  newbound = var->glbdom.ub;
6572  }
6573  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6574 
6575  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6576 
6577  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6578 
6579  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6580  return SCIP_OKAY;
6581 
6582  /* check bound on debugging solution */
6583  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6584 
6585  /* change the bound */
6586  oldbound = var->glbdom.lb;
6587  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6588  var->glbdom.lb = newbound;
6589  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6590  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6591 
6592  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6593  {
6594  /* merges overlapping holes into single holes, moves bounds respectively */
6595  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6596  }
6597 
6598  /* update the root bound changes counters */
6599  varIncRootboundchgs(var, set, stat);
6600 
6601  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6602  * redundant bound changes to be branching decisions
6603  */
6604  for( i = 0; i < var->nlbchginfos; ++i )
6605  {
6606  assert(var->lbchginfos[i].var == var);
6607 
6608  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6609  {
6610  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6611  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6612  var->lbchginfos[i].oldbound = var->glbdom.lb;
6613  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6614  {
6615  /* this bound change is redundant due to the new global bound */
6616  var->lbchginfos[i].newbound = var->glbdom.lb;
6617  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6618  var->lbchginfos[i].redundant = TRUE;
6619  }
6620  else
6621  break; /* from now on, the remaining local bound changes are not redundant */
6622  }
6623  else
6624  break; /* from now on, the remaining local bound changes are not redundant */
6625  }
6626 
6627  /* remove redundant implications and variable bounds */
6629  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6630  {
6631  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6632  }
6633 
6634  /* issue bound change event */
6635  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6636  if( var->eventfilter != NULL )
6637  {
6638  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6639  }
6640 
6641  /* process parent variables */
6642  for( i = 0; i < var->nparentvars; ++i )
6643  {
6644  parentvar = var->parentvars[i];
6645  assert(parentvar != NULL);
6646 
6647  switch( SCIPvarGetStatus(parentvar) )
6648  {
6650  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6651  break;
6652 
6653  case SCIP_VARSTATUS_COLUMN:
6654  case SCIP_VARSTATUS_LOOSE:
6655  case SCIP_VARSTATUS_FIXED:
6657  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6658  return SCIP_INVALIDDATA;
6659 
6660  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6661  assert(parentvar->data.aggregate.var == var);
6662  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6663  {
6664  SCIP_Real parentnewbound;
6665 
6666  /* a > 0 -> change lower bound of y */
6667  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6668  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6669  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6670 
6671  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6672  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6673  else
6674  parentnewbound = newbound;
6675  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6676  }
6677  else
6678  {
6679  SCIP_Real parentnewbound;
6680 
6681  /* a < 0 -> change upper bound of y */
6682  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6683  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6684  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6685  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6686 
6687  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6688  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6689  else
6690  parentnewbound = -newbound;
6691  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6692  }
6693  break;
6694 
6695  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6696  assert(parentvar->negatedvar != NULL);
6697  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6698  assert(parentvar->negatedvar->negatedvar == parentvar);
6699  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6700  parentvar->data.negate.constant - newbound) );
6701  break;
6702 
6703  default:
6704  SCIPerrorMessage("unknown variable status\n");
6705  return SCIP_INVALIDDATA;
6706  }
6707  }
6708 
6709  return SCIP_OKAY;
6710 }
6711 
6712 /** performs the current change in upper bound, changes all parents accordingly */
6713 static
6715  SCIP_VAR* var, /**< problem variable to change */
6716  BMS_BLKMEM* blkmem, /**< block memory */
6717  SCIP_SET* set, /**< global SCIP settings */
6718  SCIP_STAT* stat, /**< problem statistics */
6719  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6720  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6721  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6722  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6723  SCIP_Real newbound /**< new bound for variable */
6724  )
6725 {
6726  SCIP_VAR* parentvar;
6727  SCIP_Real oldbound;
6728  int i;
6729 
6730  assert(var != NULL);
6731  /* local domains can violate global bounds but not more than feasibility epsilon */
6732  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6733  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6734  assert(blkmem != NULL);
6735  assert(set != NULL);
6736  assert(var->scip == set->scip);
6737  assert(stat != NULL);
6738 
6739  /* adjust bound to integral value if variable is of integral type */
6740  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6741 
6742  /* check that the bound is feasible */
6743  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6744  {
6745  /* due to numerics we only want to be feasible in feasibility tolerance */
6746  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6747  newbound = var->glbdom.lb;
6748  }
6749  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6750 
6751  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6752 
6753  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6754 
6755  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6756  return SCIP_OKAY;
6757 
6758  /* check bound on debugging solution */
6759  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6760 
6761  /* change the bound */
6762  oldbound = var->glbdom.ub;
6763  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6764  var->glbdom.ub = newbound;
6765  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6766  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6767 
6768  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6769  {
6770  /* merges overlapping holes into single holes, moves bounds respectively */
6771  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6772  }
6773 
6774  /* update the root bound changes counters */
6775  varIncRootboundchgs(var, set, stat);
6776 
6777  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6778  * redundant bound changes to be branching decisions
6779  */
6780  for( i = 0; i < var->nubchginfos; ++i )
6781  {
6782  assert(var->ubchginfos[i].var == var);
6783  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6784  {
6785  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6786  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6787  var->ubchginfos[i].oldbound = var->glbdom.ub;
6788  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6789  {
6790  /* this bound change is redundant due to the new global bound */
6791  var->ubchginfos[i].newbound = var->glbdom.ub;
6792  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6793  var->ubchginfos[i].redundant = TRUE;
6794  }
6795  else
6796  break; /* from now on, the remaining local bound changes are not redundant */
6797  }
6798  else
6799  break; /* from now on, the remaining local bound changes are not redundant */
6800  }
6801 
6802  /* remove redundant implications and variable bounds */
6804  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6805  {
6806  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6807  }
6808 
6809  /* issue bound change event */
6810  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6811  if( var->eventfilter != NULL )
6812  {
6813  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6814  }
6815 
6816  /* process parent variables */
6817  for( i = 0; i < var->nparentvars; ++i )
6818  {
6819  parentvar = var->parentvars[i];
6820  assert(parentvar != NULL);
6821 
6822  switch( SCIPvarGetStatus(parentvar) )
6823  {
6825  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6826  break;
6827 
6828  case SCIP_VARSTATUS_COLUMN:
6829  case SCIP_VARSTATUS_LOOSE:
6830  case SCIP_VARSTATUS_FIXED:
6832  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6833  return SCIP_INVALIDDATA;
6834 
6835  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6836  assert(parentvar->data.aggregate.var == var);
6837  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6838  {
6839  SCIP_Real parentnewbound;
6840 
6841  /* a > 0 -> change upper bound of y */
6842  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
6843  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6844  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6845  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6846  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6847  else
6848  parentnewbound = newbound;
6849  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6850  }
6851  else
6852  {
6853  SCIP_Real parentnewbound;
6854 
6855  /* a < 0 -> change lower bound of y */
6856  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6857  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
6858  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6859  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6860  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6861  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6862  else
6863  parentnewbound = -newbound;
6864  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6865  }
6866  break;
6867 
6868  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6869  assert(parentvar->negatedvar != NULL);
6870  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6871  assert(parentvar->negatedvar->negatedvar == parentvar);
6872  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6873  parentvar->data.negate.constant - newbound) );
6874  break;
6875 
6876  default:
6877  SCIPerrorMessage("unknown variable status\n");
6878  return SCIP_INVALIDDATA;
6879  }
6880  }
6881 
6882  return SCIP_OKAY;
6883 }
6884 
6885 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6886  * updates local lower bound if the global bound is tighter
6887  */
6889  SCIP_VAR* var, /**< problem variable to change */
6890  BMS_BLKMEM* blkmem, /**< block memory */
6891  SCIP_SET* set, /**< global SCIP settings */
6892  SCIP_STAT* stat, /**< problem statistics */
6893  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6894  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6895  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6896  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6897  SCIP_Real newbound /**< new bound for variable */
6898  )
6899 {
6900  assert(var != NULL);
6901  assert(blkmem != NULL);
6902  assert(set != NULL);
6903  assert(var->scip == set->scip);
6904 
6905  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6906  * of the domain within feastol
6907  */
6908  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6909 
6910  /* adjust bound to integral value if variable is of integral type */
6911  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6912 
6913  /* check that the adjusted bound is feasible
6914  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6915  * here because we reset bounds to their original value!
6916  */
6917  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6918 
6919  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6920  {
6921  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6922  newbound = MIN(newbound, var->glbdom.ub);
6923  }
6924  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6925 
6926  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6927  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6928  */
6929  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6930 
6931  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6932 
6933  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6934  return SCIP_OKAY;
6935 
6936  /* change bounds of attached variables */
6937  switch( SCIPvarGetStatus(var) )
6938  {
6940  if( var->data.original.transvar != NULL )
6941  {
6942  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6943  cliquetable, newbound) );
6944  }
6945  else
6946  {
6947  assert(set->stage == SCIP_STAGE_PROBLEM);
6948  if( newbound > SCIPvarGetLbLocal(var) )
6949  {
6950  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6951  }
6952  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6953  }
6954  break;
6955 
6956  case SCIP_VARSTATUS_COLUMN:
6957  case SCIP_VARSTATUS_LOOSE:
6958  if( newbound > SCIPvarGetLbLocal(var) )
6959  {
6960  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6961  }
6962  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6963  break;
6964 
6965  case SCIP_VARSTATUS_FIXED:
6966  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6967  return SCIP_INVALIDDATA;
6968 
6969  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6970  assert(var->data.aggregate.var != NULL);
6971  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6972  {
6973  SCIP_Real childnewbound;
6974 
6975  /* a > 0 -> change lower bound of y */
6976  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6977  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6979  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6980  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6981  else
6982  childnewbound = newbound;
6983  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6984  childnewbound) );
6985  }
6986  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6987  {
6988  SCIP_Real childnewbound;
6989 
6990  /* a < 0 -> change upper bound of y */
6991  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6992  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6994  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6995  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6996  else
6997  childnewbound = -newbound;
6998  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6999  childnewbound) );
7000  }
7001  else
7002  {
7003  SCIPerrorMessage("scalar is zero in aggregation\n");
7004  return SCIP_INVALIDDATA;
7005  }
7006  break;
7007 
7009  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7010  return SCIP_INVALIDDATA;
7011 
7012  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7013  assert(var->negatedvar != NULL);
7015  assert(var->negatedvar->negatedvar == var);
7016  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7017  var->data.negate.constant - newbound) );
7018  break;
7019 
7020  default:
7021  SCIPerrorMessage("unknown variable status\n");
7022  return SCIP_INVALIDDATA;
7023  }
7024 
7025  return SCIP_OKAY;
7026 }
7027 
7028 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7029  * updates local upper bound if the global bound is tighter
7030  */
7032  SCIP_VAR* var, /**< problem variable to change */
7033  BMS_BLKMEM* blkmem, /**< block memory */
7034  SCIP_SET* set, /**< global SCIP settings */
7035  SCIP_STAT* stat, /**< problem statistics */
7036  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7037  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7038  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7039  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7040  SCIP_Real newbound /**< new bound for variable */
7041  )
7042 {
7043  assert(var != NULL);
7044  assert(blkmem != NULL);
7045  assert(set != NULL);
7046  assert(var->scip == set->scip);
7047 
7048  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7049  * of the domain within feastol
7050  */
7051  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7052 
7053  /* adjust bound to integral value if variable is of integral type */
7054  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7055 
7056  /* check that the adjusted bound is feasible
7057  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7058  * here because we reset bounds to their original value!
7059  */
7060  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7061 
7062  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7063  {
7064  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7065  newbound = MAX(newbound, var->glbdom.lb);
7066  }
7067  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7068 
7069  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7070  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7071  */
7072  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7073 
7074  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7075 
7076  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
7077  return SCIP_OKAY;
7078 
7079  /* change bounds of attached variables */
7080  switch( SCIPvarGetStatus(var) )
7081  {
7083  if( var->data.original.transvar != NULL )
7084  {
7085  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7086  newbound) );
7087  }
7088  else
7089  {
7090  assert(set->stage == SCIP_STAGE_PROBLEM);
7091  if( newbound < SCIPvarGetUbLocal(var) )
7092  {
7093  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7094  }
7095  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7096  }
7097  break;
7098 
7099  case SCIP_VARSTATUS_COLUMN:
7100  case SCIP_VARSTATUS_LOOSE:
7101  if( newbound < SCIPvarGetUbLocal(var) )
7102  {
7103  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7104  }
7105  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7106  break;
7107 
7108  case SCIP_VARSTATUS_FIXED:
7109  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7110  return SCIP_INVALIDDATA;
7111 
7112  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7113  assert(var->data.aggregate.var != NULL);
7114  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7115  {
7116  SCIP_Real childnewbound;
7117 
7118  /* a > 0 -> change lower bound of y */
7119  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7120  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7122  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7123  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7124  else
7125  childnewbound = newbound;
7126  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7127  childnewbound) );
7128  }
7129  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7130  {
7131  SCIP_Real childnewbound;
7132 
7133  /* a < 0 -> change upper bound of y */
7134  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7135  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7137  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7138  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7139  else
7140  childnewbound = -newbound;
7141  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7142  childnewbound) );
7143  }
7144  else
7145  {
7146  SCIPerrorMessage("scalar is zero in aggregation\n");
7147  return SCIP_INVALIDDATA;
7148  }
7149  break;
7150 
7152  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7153  return SCIP_INVALIDDATA;
7154 
7155  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7156  assert(var->negatedvar != NULL);
7158  assert(var->negatedvar->negatedvar == var);
7159  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7160  var->data.negate.constant - newbound) );
7161  break;
7162 
7163  default:
7164  SCIPerrorMessage("unknown variable status\n");
7165  return SCIP_INVALIDDATA;
7166  }
7167 
7168  return SCIP_OKAY;
7169 }
7170 
7171 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7173  SCIP_VAR* var, /**< problem variable */
7174  SCIP_SET* set, /**< global SCIP settings */
7175  SCIP_Real lazylb /**< the lazy lower bound to be set */
7176  )
7177 {
7178  assert(var != NULL);
7179  assert(var->probindex != -1);
7180  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7181  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7182  assert(set != NULL);
7183  assert(var->scip == set->scip);
7184 
7185  /* variable should not be in the LP */
7187  return SCIP_INVALIDCALL;
7188 
7189  var->lazylb = lazylb;
7190 
7191  return SCIP_OKAY;
7192 }
7193 
7194 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7196  SCIP_VAR* var, /**< problem variable */
7197  SCIP_SET* set, /**< global SCIP settings */
7198  SCIP_Real lazyub /**< the lazy lower bound to be set */
7199  )
7200 {
7201  assert(var != NULL);
7202  assert(var->probindex != -1);
7203  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7204  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7205  assert(set != NULL);
7206  assert(var->scip == set->scip);
7207 
7208  /* variable should not be in the LP */
7210  return SCIP_INVALIDCALL;
7211 
7212  var->lazyub = lazyub;
7213 
7214  return SCIP_OKAY;
7215 }
7216 
7217 
7218 /** changes global bound of variable; if possible, adjusts bound to integral value;
7219  * updates local bound if the global bound is tighter
7220  */
7222  SCIP_VAR* var, /**< problem variable to change */
7223  BMS_BLKMEM* blkmem, /**< block memory */
7224  SCIP_SET* set, /**< global SCIP settings */
7225  SCIP_STAT* stat, /**< problem statistics */
7226  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7227  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7228  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7229  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7230  SCIP_Real newbound, /**< new bound for variable */
7231  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7232  )
7233 {
7234  /* apply bound change to the LP data */
7235  switch( boundtype )
7236  {
7237  case SCIP_BOUNDTYPE_LOWER:
7238  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7239  case SCIP_BOUNDTYPE_UPPER:
7240  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7241  default:
7242  SCIPerrorMessage("unknown bound type\n");
7243  return SCIP_INVALIDDATA;
7244  }
7245 }
7246 
7247 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7248 static
7250  SCIP_VAR* var, /**< problem variable to change */
7251  BMS_BLKMEM* blkmem, /**< block memory */
7252  SCIP_SET* set, /**< global SCIP settings */
7253  SCIP_LP* lp, /**< current LP data */
7254  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7255  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7256  SCIP_Real oldbound, /**< old lower bound for variable */
7257  SCIP_Real newbound /**< new lower bound for variable */
7258  )
7259 {
7260  assert(var != NULL);
7261  assert(var->eventfilter != NULL);
7262  assert(SCIPvarIsTransformed(var));
7263  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb); /*lint !e777*/
7264  assert(set != NULL);
7265  assert(var->scip == set->scip);
7266 
7267  /* check, if the variable is being tracked for bound changes
7268  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7269  */
7270  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7273  {
7274  SCIP_EVENT* event;
7275 
7276  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7277 
7278  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7279  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7280  }
7281 
7282  return SCIP_OKAY;
7283 }
7284 
7285 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7286 static
7288  SCIP_VAR* var, /**< problem variable to change */
7289  BMS_BLKMEM* blkmem, /**< block memory */
7290  SCIP_SET* set, /**< global SCIP settings */
7291  SCIP_LP* lp, /**< current LP data */
7292  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7293  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7294  SCIP_Real oldbound, /**< old upper bound for variable */
7295  SCIP_Real newbound /**< new upper bound for variable */
7296  )
7297 {
7298  assert(var != NULL);
7299  assert(var->eventfilter != NULL);
7300  assert(SCIPvarIsTransformed(var));
7301  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub); /*lint !e777*/
7302  assert(set != NULL);
7303  assert(var->scip == set->scip);
7304 
7305  /* check, if the variable is being tracked for bound changes
7306  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7307  */
7308  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7311  {
7312  SCIP_EVENT* event;
7313 
7314  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7315 
7316  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7317  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7318  }
7319 
7320  return SCIP_OKAY;
7321 }
7322 
7323 /* forward declaration, because both methods call each other recursively */
7324 
7325 /* performs the current change in upper bound, changes all parents accordingly */
7326 static
7328  SCIP_VAR* var, /**< problem variable to change */
7329  BMS_BLKMEM* blkmem, /**< block memory */
7330  SCIP_SET* set, /**< global SCIP settings */
7331  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7332  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7333  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7334  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7335  SCIP_Real newbound /**< new bound for variable */
7336  );
7337 
7338 /** performs the current change in lower bound, changes all parents accordingly */
7339 static
7341  SCIP_VAR* var, /**< problem variable to change */
7342  BMS_BLKMEM* blkmem, /**< block memory */
7343  SCIP_SET* set, /**< global SCIP settings */
7344  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7345  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7346  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7347  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7348  SCIP_Real newbound /**< new bound for variable */
7349  )
7350 {
7351  SCIP_VAR* parentvar;
7352  SCIP_Real oldbound;
7353  int i;
7354 
7355  assert(var != NULL);
7356  assert(set != NULL);
7357  assert(var->scip == set->scip);
7358  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7359  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7360  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7361  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7363 
7364  /* check that the bound is feasible */
7365  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7366  /* adjust bound to integral value if variable is of integral type */
7367  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7368 
7369  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7370  {
7371  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7372  newbound = MIN(newbound, var->locdom.ub);
7373 
7374  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7375  newbound = MAX(newbound, var->glbdom.lb);
7376  }
7377  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7378 
7379  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7380 
7381  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7382  newbound = var->glbdom.lb;
7383  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7384  return SCIP_OKAY;
7385 
7386  /* change the bound */
7387  oldbound = var->locdom.lb;
7388  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7389  var->locdom.lb = newbound;
7390 
7391  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7392  * once update the statistic
7393  */
7394  if( stat != NULL )
7395  SCIPstatIncrement(stat, set, domchgcount);
7396 
7397  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7398  {
7399  /* merges overlapping holes into single holes, moves bounds respectively */
7400  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7401  }
7402 
7403  /* issue bound change event */
7404  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7405  if( var->eventfilter != NULL )
7406  {
7407  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7408  }
7409 
7410  /* process parent variables */
7411  for( i = 0; i < var->nparentvars; ++i )
7412  {
7413  parentvar = var->parentvars[i];
7414  assert(parentvar != NULL);
7415 
7416  switch( SCIPvarGetStatus(parentvar) )
7417  {
7419  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7420  break;
7421 
7422  case SCIP_VARSTATUS_COLUMN:
7423  case SCIP_VARSTATUS_LOOSE:
7424  case SCIP_VARSTATUS_FIXED:
7426  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7427  return SCIP_INVALIDDATA;
7428 
7429  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7430  assert(parentvar->data.aggregate.var == var);
7431  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7432  {
7433  SCIP_Real parentnewbound;
7434 
7435  /* a > 0 -> change lower bound of y */
7436  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7437  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7438  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7439 
7440  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7441  {
7442  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7443  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7444  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7445  * as a result, the parent's lower bound is set to it's upper bound, and not above
7446  */
7447  if( parentnewbound > parentvar->glbdom.ub )
7448  {
7449  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7450  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7451  parentnewbound = parentvar->glbdom.ub;
7452  }
7453  }
7454  else
7455  parentnewbound = newbound;
7456  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7457  }
7458  else
7459  {
7460  SCIP_Real parentnewbound;
7461 
7462  /* a < 0 -> change upper bound of y */
7463  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7464  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7465  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7466  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7467 
7468  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7469  {
7470  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7471  /* 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
7472  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7473  * as a result, the parent's upper bound is set to it's lower bound, and not below
7474  */
7475  if( parentnewbound < parentvar->glbdom.lb )
7476  {
7477  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7478  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7479  parentnewbound = parentvar->glbdom.lb;
7480  }
7481  }
7482  else
7483  parentnewbound = -newbound;
7484  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7485  }
7486  break;
7487 
7488  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7489  assert(parentvar->negatedvar != NULL);
7490  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7491  assert(parentvar->negatedvar->negatedvar == parentvar);
7492  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7493  parentvar->data.negate.constant - newbound) );
7494  break;
7495 
7496  default:
7497  SCIPerrorMessage("unknown variable status\n");
7498  return SCIP_INVALIDDATA;
7499  }
7500  }
7501 
7502  return SCIP_OKAY;
7503 }
7504 
7505 /** performs the current change in upper bound, changes all parents accordingly */
7506 static
7508  SCIP_VAR* var, /**< problem variable to change */
7509  BMS_BLKMEM* blkmem, /**< block memory */
7510  SCIP_SET* set, /**< global SCIP settings */
7511  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7512  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7513  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7514  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7515  SCIP_Real newbound /**< new bound for variable */
7516  )
7517 {
7518  SCIP_VAR* parentvar;
7519  SCIP_Real oldbound;
7520  int i;
7521 
7522  assert(var != NULL);
7523  assert(set != NULL);
7524  assert(var->scip == set->scip);
7525  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7526  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7527  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7528  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7530 
7531  /* check that the bound is feasible */
7532  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7533  /* adjust bound to integral value if variable is of integral type */
7534  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7535 
7536  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7537  {
7538  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7539  newbound = MAX(newbound, var->locdom.lb);
7540 
7541  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7542  newbound = MIN(newbound, var->glbdom.ub);
7543  }
7544  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7545 
7546  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7547 
7548  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7549  newbound = var->glbdom.ub;
7550  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7551  return SCIP_OKAY;
7552 
7553  /* change the bound */
7554  oldbound = var->locdom.ub;
7555  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7556  var->locdom.ub = newbound;
7557 
7558  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7559  * once update the statistic
7560  */
7561  if( stat != NULL )
7562  SCIPstatIncrement(stat, set, domchgcount);
7563 
7564  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7565  {
7566  /* merges overlapping holes into single holes, moves bounds respectively */
7567  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7568  }
7569 
7570  /* issue bound change event */
7571  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7572  if( var->eventfilter != NULL )
7573  {
7574  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7575  }
7576 
7577  /* process parent variables */
7578  for( i = 0; i < var->nparentvars; ++i )
7579  {
7580  parentvar = var->parentvars[i];
7581  assert(parentvar != NULL);
7582 
7583  switch( SCIPvarGetStatus(parentvar) )
7584  {
7586  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7587  break;
7588 
7589  case SCIP_VARSTATUS_COLUMN:
7590  case SCIP_VARSTATUS_LOOSE:
7591  case SCIP_VARSTATUS_FIXED:
7593  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7594  return SCIP_INVALIDDATA;
7595 
7596  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7597  assert(parentvar->data.aggregate.var == var);
7598  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7599  {
7600  SCIP_Real parentnewbound;
7601 
7602  /* a > 0 -> change upper bound of x */
7603  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7604  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7605  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7606  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7607  {
7608  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7609  /* 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
7610  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7611  * as a result, the parent's upper bound is set to it's lower bound, and not below
7612  */
7613  if( parentnewbound < parentvar->glbdom.lb )
7614  {
7615  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7616  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7617  parentnewbound = parentvar->glbdom.lb;
7618  }
7619  }
7620  else
7621  parentnewbound = newbound;
7622  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7623  }
7624  else
7625  {
7626  SCIP_Real parentnewbound;
7627 
7628  /* a < 0 -> change lower bound of x */
7629  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7630  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7631  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7632  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7633  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7634  {
7635  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7636  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7637  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7638  * as a result, the parent's lower bound is set to it's upper bound, and not above
7639  */
7640  if( parentnewbound > parentvar->glbdom.ub )
7641  {
7642  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7643  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7644  parentnewbound = parentvar->glbdom.ub;
7645  }
7646  }
7647  else
7648  parentnewbound = -newbound;
7649  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7650  }
7651  break;
7652 
7653  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7654  assert(parentvar->negatedvar != NULL);
7655  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7656  assert(parentvar->negatedvar->negatedvar == parentvar);
7657  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7658  parentvar->data.negate.constant - newbound) );
7659  break;
7660 
7661  default:
7662  SCIPerrorMessage("unknown variable status\n");
7663  return SCIP_INVALIDDATA;
7664  }
7665  }
7666 
7667  return SCIP_OKAY;
7668 }
7669 
7670 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7671  * information in variable
7672  */
7674  SCIP_VAR* var, /**< problem variable to change */
7675  BMS_BLKMEM* blkmem, /**< block memory */
7676  SCIP_SET* set, /**< global SCIP settings */
7677  SCIP_STAT* stat, /**< problem statistics */
7678  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7679  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7680  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7681  SCIP_Real newbound /**< new bound for variable */
7682  )
7683 {
7684  assert(var != NULL);
7685  assert(blkmem != NULL);
7686  assert(set != NULL);
7687  assert(var->scip == set->scip);
7688 
7689  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7690  * of the domain within feastol
7691  */
7692  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7693 
7694  /* adjust bound to integral value if variable is of integral type */
7695  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7696 
7697  /* check that the adjusted bound is feasible */
7698  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7699 
7700  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7701  {
7702  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7703  newbound = MIN(newbound, var->locdom.ub);
7704  }
7705  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7706 
7707  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7708 
7709  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) ) /*lint !e777*/
7710  return SCIP_OKAY;
7711 
7712  /* change bounds of attached variables */
7713  switch( SCIPvarGetStatus(var) )
7714  {
7716  if( var->data.original.transvar != NULL )
7717  {
7718  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7719  newbound) );
7720  }
7721  else
7722  {
7723  assert(set->stage == SCIP_STAGE_PROBLEM);
7724  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7725  }
7726  break;
7727 
7728  case SCIP_VARSTATUS_COLUMN:
7729  case SCIP_VARSTATUS_LOOSE:
7730  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7731  break;
7732 
7733  case SCIP_VARSTATUS_FIXED:
7734  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7735  return SCIP_INVALIDDATA;
7736 
7737  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7738  assert(var->data.aggregate.var != NULL);
7739  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7740  {
7741  SCIP_Real childnewbound;
7742 
7743  /* a > 0 -> change lower bound of y */
7744  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7745  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7747  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7748  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7749  else
7750  childnewbound = newbound;
7751  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7752  childnewbound) );
7753  }
7754  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7755  {
7756  SCIP_Real childnewbound;
7757 
7758  /* a < 0 -> change upper bound of y */
7759  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7760  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7762  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7763  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7764  else
7765  childnewbound = -newbound;
7766  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7767  childnewbound) );
7768  }
7769  else
7770  {
7771  SCIPerrorMessage("scalar is zero in aggregation\n");
7772  return SCIP_INVALIDDATA;
7773  }
7774  break;
7775 
7777  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7778  return SCIP_INVALIDDATA;
7779 
7780  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7781  assert(var->negatedvar != NULL);
7783  assert(var->negatedvar->negatedvar == var);
7784  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7785  var->data.negate.constant - newbound) );
7786  break;
7787 
7788  default:
7789  SCIPerrorMessage("unknown variable status\n");
7790  return SCIP_INVALIDDATA;
7791  }
7792 
7793  return SCIP_OKAY;
7794 }
7795 
7796 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7797  * information in variable
7798  */
7800  SCIP_VAR* var, /**< problem variable to change */
7801  BMS_BLKMEM* blkmem, /**< block memory */
7802  SCIP_SET* set, /**< global SCIP settings */
7803  SCIP_STAT* stat, /**< problem statistics */
7804  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7805  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7806  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7807  SCIP_Real newbound /**< new bound for variable */
7808  )
7809 {
7810  assert(var != NULL);
7811  assert(blkmem != NULL);
7812  assert(set != NULL);
7813  assert(var->scip == set->scip);
7814 
7815  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7816  * of the domain within feastol
7817  */
7818  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7819 
7820  /* adjust bound to integral value if variable is of integral type */
7821  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7822 
7823  /* check that the adjusted bound is feasible */
7824  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7825 
7826  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7827  {
7828  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7829  newbound = MAX(newbound, var->locdom.lb);
7830  }
7831  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7832 
7833  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7834 
7835  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) ) /*lint !e777*/
7836  return SCIP_OKAY;
7837 
7838  /* change bounds of attached variables */
7839  switch( SCIPvarGetStatus(var) )
7840  {
7842  if( var->data.original.transvar != NULL )
7843  {
7844  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7845  }
7846  else
7847  {
7848  assert(set->stage == SCIP_STAGE_PROBLEM);
7849  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7850  }
7851  break;
7852 
7853  case SCIP_VARSTATUS_COLUMN:
7854  case SCIP_VARSTATUS_LOOSE:
7855  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7856  break;
7857 
7858  case SCIP_VARSTATUS_FIXED:
7859  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7860  return SCIP_INVALIDDATA;
7861 
7862  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7863  assert(var->data.aggregate.var != NULL);
7864  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7865  {
7866  SCIP_Real childnewbound;
7867 
7868  /* a > 0 -> change upper bound of y */
7869  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7870  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7872  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7873  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7874  else
7875  childnewbound = newbound;
7876  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7877  childnewbound) );
7878  }
7879  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7880  {
7881  SCIP_Real childnewbound;
7882 
7883  /* a < 0 -> change lower bound of y */
7884  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7885  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7887  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7888  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7889  else
7890  childnewbound = -newbound;
7891  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7892  childnewbound) );
7893  }
7894  else
7895  {
7896  SCIPerrorMessage("scalar is zero in aggregation\n");
7897  return SCIP_INVALIDDATA;
7898  }
7899  break;
7900 
7902  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7903  return SCIP_INVALIDDATA;
7904 
7905  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7906  assert(var->negatedvar != NULL);
7908  assert(var->negatedvar->negatedvar == var);
7909  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7910  var->data.negate.constant - newbound) );
7911  break;
7912 
7913  default:
7914  SCIPerrorMessage("unknown variable status\n");
7915  return SCIP_INVALIDDATA;
7916  }
7917 
7918  return SCIP_OKAY;
7919 }
7920 
7921 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7922  * information in variable
7923  */
7925  SCIP_VAR* var, /**< problem variable to change */
7926  BMS_BLKMEM* blkmem, /**< block memory */
7927  SCIP_SET* set, /**< global SCIP settings */
7928  SCIP_STAT* stat, /**< problem statistics */
7929  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7930  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7931  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7932  SCIP_Real newbound, /**< new bound for variable */
7933  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7934  )
7935 {
7936  /* apply bound change to the LP data */
7937  switch( boundtype )
7938  {
7939  case SCIP_BOUNDTYPE_LOWER:
7940  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7941  case SCIP_BOUNDTYPE_UPPER:
7942  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7943  default:
7944  SCIPerrorMessage("unknown bound type\n");
7945  return SCIP_INVALIDDATA;
7946  }
7947 }
7948 
7949 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7951  SCIP_VAR* var, /**< problem variable to change */
7952  SCIP_SET* set, /**< global SCIP settings */
7953  SCIP_LP* lp, /**< current LP data */
7954  SCIP_Real newbound /**< new bound for variable */
7955  )
7956 {
7957  assert(var != NULL);
7958  assert(set != NULL);
7959  assert(var->scip == set->scip);
7960  assert(lp != NULL);
7961  assert(SCIPlpDiving(lp));
7962 
7963  /* adjust bound for integral variables */
7964  SCIPvarAdjustLb(var, set, &newbound);
7965 
7966  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7967 
7968  /* change bounds of attached variables */
7969  switch( SCIPvarGetStatus(var) )
7970  {
7972  assert(var->data.original.transvar != NULL);
7973  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7974  break;
7975 
7976  case SCIP_VARSTATUS_COLUMN:
7977  assert(var->data.col != NULL);
7978  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7979  break;
7980 
7981  case SCIP_VARSTATUS_LOOSE:
7982  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7983  return SCIP_INVALIDDATA;
7984 
7985  case SCIP_VARSTATUS_FIXED:
7986  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7987  return SCIP_INVALIDDATA;
7988 
7989  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7990  assert(var->data.aggregate.var != NULL);
7991  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7992  {
7993  SCIP_Real childnewbound;
7994 
7995  /* a > 0 -> change lower bound of y */
7996  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7997  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7998  else
7999  childnewbound = newbound;
8000  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8001  }
8002  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8003  {
8004  SCIP_Real childnewbound;
8005 
8006  /* a < 0 -> change upper bound of y */
8007  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8008  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8009  else
8010  childnewbound = -newbound;
8011  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8012  }
8013  else
8014  {
8015  SCIPerrorMessage("scalar is zero in aggregation\n");
8016  return SCIP_INVALIDDATA;
8017  }
8018  break;
8019 
8021  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8022  return SCIP_INVALIDDATA;
8023 
8024  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8025  assert(var->negatedvar != NULL);
8027  assert(var->negatedvar->negatedvar == var);
8028  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8029  break;
8030 
8031  default:
8032  SCIPerrorMessage("unknown variable status\n");
8033  return SCIP_INVALIDDATA;
8034  }
8035 
8036  return SCIP_OKAY;
8037 }
8038 
8039 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8041  SCIP_VAR* var, /**< problem variable to change */
8042  SCIP_SET* set, /**< global SCIP settings */
8043  SCIP_LP* lp, /**< current LP data */
8044  SCIP_Real newbound /**< new bound for variable */
8045  )
8046 {
8047  assert(var != NULL);
8048  assert(set != NULL);
8049  assert(var->scip == set->scip);
8050  assert(lp != NULL);
8051  assert(SCIPlpDiving(lp));
8052 
8053  /* adjust bound for integral variables */
8054  SCIPvarAdjustUb(var, set, &newbound);
8055 
8056  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8057 
8058  /* change bounds of attached variables */
8059  switch( SCIPvarGetStatus(var) )
8060  {
8062  assert(var->data.original.transvar != NULL);
8063  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8064  break;
8065 
8066  case SCIP_VARSTATUS_COLUMN:
8067  assert(var->data.col != NULL);
8068  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8069  break;
8070 
8071  case SCIP_VARSTATUS_LOOSE:
8072  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8073  return SCIP_INVALIDDATA;
8074 
8075  case SCIP_VARSTATUS_FIXED:
8076  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8077  return SCIP_INVALIDDATA;
8078 
8079  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8080  assert(var->data.aggregate.var != NULL);
8081  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8082  {
8083  SCIP_Real childnewbound;
8084 
8085  /* a > 0 -> change upper bound of y */
8086  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8087  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8088  else
8089  childnewbound = newbound;
8090  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8091  }
8092  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8093  {
8094  SCIP_Real childnewbound;
8095 
8096  /* a < 0 -> change lower bound of y */
8097  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8098  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8099  else
8100  childnewbound = -newbound;
8101  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8102  }
8103  else
8104  {
8105  SCIPerrorMessage("scalar is zero in aggregation\n");
8106  return SCIP_INVALIDDATA;
8107  }
8108  break;
8109 
8111  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8112  return SCIP_INVALIDDATA;
8113 
8114  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8115  assert(var->negatedvar != NULL);
8117  assert(var->negatedvar->negatedvar == var);
8118  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8119  break;
8120 
8121  default:
8122  SCIPerrorMessage("unknown variable status\n");
8123  return SCIP_INVALIDDATA;
8124  }
8125 
8126  return SCIP_OKAY;
8127 }
8128 
8129 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8130  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8131  * not updated if bounds of aggregation variables are changing
8132  *
8133  * calling this function for a non-multi-aggregated variable is not allowed
8134  */
8136  SCIP_VAR* var, /**< problem variable */
8137  SCIP_SET* set /**< global SCIP settings */
8138  )
8139 {
8140  int i;
8141  SCIP_Real lb;
8142  SCIP_Real bnd;
8143  SCIP_VAR* aggrvar;
8144  SCIP_Bool posinf;
8145  SCIP_Bool neginf;
8146 
8147  assert(var != NULL);
8148  assert(set != NULL);
8149  assert(var->scip == set->scip);
8151 
8152  posinf = FALSE;
8153  neginf = FALSE;
8154  lb = var->data.multaggr.constant;
8155  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8156  {
8157  aggrvar = var->data.multaggr.vars[i];
8158  if( var->data.multaggr.scalars[i] > 0.0 )
8159  {
8160  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8161 
8162  if( SCIPsetIsInfinity(set, bnd) )
8163  posinf = TRUE;
8164  else if( SCIPsetIsInfinity(set, -bnd) )
8165  neginf = TRUE;
8166  else
8167  lb += var->data.multaggr.scalars[i] * bnd;
8168  }
8169  else
8170  {
8171  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8172 
8173  if( SCIPsetIsInfinity(set, -bnd) )
8174  posinf = TRUE;
8175  else if( SCIPsetIsInfinity(set, bnd) )
8176  neginf = TRUE;
8177  else
8178  lb += var->data.multaggr.scalars[i] * bnd;
8179  }
8180 
8181  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8182  * variable
8183  */
8184  if( neginf )
8185  return SCIPvarGetLbLocal(var);
8186  }
8187 
8188  /* if positive infinity flag was set to true return infinity */
8189  if( posinf )
8190  return SCIPsetInfinity(set);
8191 
8192  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8193 }
8194 
8195 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8196  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8197  * not updated if bounds of aggregation variables are changing
8198  *
8199  * calling this function for a non-multi-aggregated variable is not allowed
8200  */
8202  SCIP_VAR* var, /**< problem variable */
8203  SCIP_SET* set /**< global SCIP settings */
8204  )
8205 {
8206  int i;
8207  SCIP_Real ub;
8208  SCIP_Real bnd;
8209  SCIP_VAR* aggrvar;
8210  SCIP_Bool posinf;
8211  SCIP_Bool neginf;
8212 
8213  assert(var != NULL);
8214  assert(set != NULL);
8215  assert(var->scip == set->scip);
8217 
8218  posinf = FALSE;
8219  neginf = FALSE;
8220  ub = var->data.multaggr.constant;
8221  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8222  {
8223  aggrvar = var->data.multaggr.vars[i];
8224  if( var->data.multaggr.scalars[i] > 0.0 )
8225  {
8226  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8227 
8228  if( SCIPsetIsInfinity(set, bnd) )
8229  posinf = TRUE;
8230  else if( SCIPsetIsInfinity(set, -bnd) )
8231  neginf = TRUE;
8232  else
8233  ub += var->data.multaggr.scalars[i] * bnd;
8234  }
8235  else
8236  {
8237  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8238 
8239  if( SCIPsetIsInfinity(set, -bnd) )
8240  posinf = TRUE;
8241  else if( SCIPsetIsInfinity(set, bnd) )
8242  neginf = TRUE;
8243  else
8244  ub += var->data.multaggr.scalars[i] * bnd;
8245  }
8246 
8247  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8248  * variable
8249  */
8250  if( posinf )
8251  return SCIPvarGetUbLocal(var);
8252  }
8253 
8254  /* if negative infinity flag was set to true return -infinity */
8255  if( neginf )
8256  return -SCIPsetInfinity(set);
8257 
8258  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8259 }
8260 
8261 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8262  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8263  * not updated if bounds of aggregation variables are changing
8264  *
8265  * calling this function for a non-multi-aggregated variable is not allowed
8266  */
8268  SCIP_VAR* var, /**< problem variable */
8269  SCIP_SET* set /**< global SCIP settings */
8270  )
8271 {
8272  int i;
8273  SCIP_Real lb;
8274  SCIP_Real bnd;
8275  SCIP_VAR* aggrvar;
8276  SCIP_Bool posinf;
8277  SCIP_Bool neginf;
8278 
8279  assert(var != NULL);
8280  assert(set != NULL);
8281  assert(var->scip == set->scip);
8283 
8284  posinf = FALSE;
8285  neginf = FALSE;
8286  lb = var->data.multaggr.constant;
8287  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8288  {
8289  aggrvar = var->data.multaggr.vars[i];
8290  if( var->data.multaggr.scalars[i] > 0.0 )
8291  {
8292  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8293 
8294  if( SCIPsetIsInfinity(set, bnd) )
8295  posinf = TRUE;
8296  else if( SCIPsetIsInfinity(set, -bnd) )
8297  neginf = TRUE;
8298  else
8299  lb += var->data.multaggr.scalars[i] * bnd;
8300  }
8301  else
8302  {
8303  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8304 
8305  if( SCIPsetIsInfinity(set, -bnd) )
8306  posinf = TRUE;
8307  else if( SCIPsetIsInfinity(set, bnd) )
8308  neginf = TRUE;
8309  else
8310  lb += var->data.multaggr.scalars[i] * bnd;
8311  }
8312 
8313  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8314  * variable
8315  */
8316  if( neginf )
8317  return SCIPvarGetLbGlobal(var);
8318  }
8319 
8320  /* if positive infinity flag was set to true return infinity */
8321  if( posinf )
8322  return SCIPsetInfinity(set);
8323 
8324  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8325 }
8326 
8327 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8328  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8329  * not updated if bounds of aggregation variables are changing
8330  *
8331  * calling this function for a non-multi-aggregated variable is not allowed
8332  */
8334  SCIP_VAR* var, /**< problem variable */
8335  SCIP_SET* set /**< global SCIP settings */
8336  )
8337 {
8338  int i;
8339  SCIP_Real ub;
8340  SCIP_Real bnd;
8341  SCIP_VAR* aggrvar;
8342  SCIP_Bool posinf;
8343  SCIP_Bool neginf;
8344 
8345  assert(var != NULL);
8346  assert(set != NULL);
8347  assert(var->scip == set->scip);
8349 
8350  posinf = FALSE;
8351  neginf = FALSE;
8352  ub = var->data.multaggr.constant;
8353  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8354  {
8355  aggrvar = var->data.multaggr.vars[i];
8356  if( var->data.multaggr.scalars[i] > 0.0 )
8357  {
8358  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8359 
8360  if( SCIPsetIsInfinity(set, bnd) )
8361  posinf = TRUE;
8362  else if( SCIPsetIsInfinity(set, -bnd) )
8363  neginf = TRUE;
8364  else
8365  ub += var->data.multaggr.scalars[i] * bnd;
8366  }
8367  else
8368  {
8369  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8370 
8371  if( SCIPsetIsInfinity(set, -bnd) )
8372  posinf = TRUE;
8373  else if( SCIPsetIsInfinity(set, bnd) )
8374  neginf = TRUE;
8375  else
8376  ub += var->data.multaggr.scalars[i] * bnd;
8377  }
8378 
8379  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8380  * variable
8381  */
8382  if( posinf )
8383  return SCIPvarGetUbGlobal(var);
8384  }
8385 
8386  /* if negative infinity flag was set to true return -infinity */
8387  if( neginf )
8388  return -SCIPsetInfinity(set);
8389 
8390  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8391 }
8392 
8393 /** adds a hole to the original domain of the variable */
8395  SCIP_VAR* var, /**< problem variable */
8396  BMS_BLKMEM* blkmem, /**< block memory */
8397  SCIP_SET* set, /**< global SCIP settings */
8398  SCIP_Real left, /**< left bound of open interval in new hole */
8399  SCIP_Real right /**< right bound of open interval in new hole */
8400  )
8401 {
8402  SCIP_Bool added;
8403 
8404  assert(var != NULL);
8405  assert(!SCIPvarIsTransformed(var));
8407  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8408  assert(set != NULL);
8409  assert(var->scip == set->scip);
8410  assert(set->stage == SCIP_STAGE_PROBLEM);
8411 
8412  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8413 
8414  if( SCIPsetIsEQ(set, left, right) )
8415  return SCIP_OKAY;
8416 
8417  /* the interval should not be empty */
8418  assert(SCIPsetIsLT(set, left, right));
8419 
8420  /* the the interval bound should already be adjusted */
8421  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8422  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8423 
8424  /* the the interval should lay between the lower and upper bound */
8425  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8426  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8427 
8428  /* add domain hole */
8429  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8430 
8431  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8432  if( added )
8433  {
8434  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8435  }
8436 
8437  /**@todo add hole in parent and child variables (just like with bound changes);
8438  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8439  */
8440 
8441  return SCIP_OKAY;
8442 }
8443 
8444 /** performs the current add of domain, changes all parents accordingly */
8445 static
8447  SCIP_VAR* var, /**< problem variable */
8448  BMS_BLKMEM* blkmem, /**< block memory */
8449  SCIP_SET* set, /**< global SCIP settings */
8450  SCIP_STAT* stat, /**< problem statistics */
8451  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8452  SCIP_Real left, /**< left bound of open interval in new hole */
8453  SCIP_Real right, /**< right bound of open interval in new hole */
8454  SCIP_Bool* added /**< pointer to store whether the hole was added */
8455  )
8456 {
8457  SCIP_VAR* parentvar;
8458  SCIP_Real newlb;
8459  SCIP_Real newub;
8460  int i;
8461 
8462  assert(var != NULL);
8463  assert(added != NULL);
8464  assert(blkmem != NULL);
8465 
8466  /* the interval should not be empty */
8467  assert(SCIPsetIsLT(set, left, right));
8468 
8469  /* the interval bound should already be adjusted */
8470  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8471  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8472 
8473  /* the interval should lay between the lower and upper bound */
8474  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8475  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8476 
8477  /* @todo add debugging mechanism for holes when using a debugging solution */
8478 
8479  /* add hole to hole list */
8480  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8481 
8482  /* check if the hole is redundant */
8483  if( !(*added) )
8484  return SCIP_OKAY;
8485 
8486  /* current bounds */
8487  newlb = var->glbdom.lb;
8488  newub = var->glbdom.ub;
8489 
8490  /* merge domain holes */
8491  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8492 
8493  /* the bound should not be changed */
8494  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8495  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8496 
8497  /* issue bound change event */
8498  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8499  if( var->eventfilter != NULL )
8500  {
8501  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8502  }
8503 
8504  /* process parent variables */
8505  for( i = 0; i < var->nparentvars; ++i )
8506  {
8507  SCIP_Real parentnewleft;
8508  SCIP_Real parentnewright;
8509  SCIP_Bool localadded;
8510 
8511  parentvar = var->parentvars[i];
8512  assert(parentvar != NULL);
8513 
8514  switch( SCIPvarGetStatus(parentvar) )
8515  {
8517  parentnewleft = left;
8518  parentnewright = right;
8519  break;
8520 
8521  case SCIP_VARSTATUS_COLUMN:
8522  case SCIP_VARSTATUS_LOOSE:
8523  case SCIP_VARSTATUS_FIXED:
8525  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8526  return SCIP_INVALIDDATA;
8527 
8528  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8529  assert(parentvar->data.aggregate.var == var);
8530 
8531  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8532  {
8533  /* a > 0 -> change upper bound of x */
8534  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8535  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8536  }
8537  else
8538  {
8539  /* a < 0 -> change lower bound of x */
8540  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8541 
8542  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8543  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8544  }
8545  break;
8546 
8547  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8548  assert(parentvar->negatedvar != NULL);
8549  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8550  assert(parentvar->negatedvar->negatedvar == parentvar);
8551 
8552  parentnewright = -left + parentvar->data.negate.constant;
8553  parentnewleft = -right + parentvar->data.negate.constant;
8554  break;
8555 
8556  default:
8557  SCIPerrorMessage("unknown variable status\n");
8558  return SCIP_INVALIDDATA;
8559  }
8560 
8561  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8562 
8563  /* perform hole added for parent variable */
8564  assert(blkmem != NULL);
8565  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8566  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8567  parentnewleft, parentnewright, &localadded) );
8568  assert(localadded);
8569  }
8570 
8571  return SCIP_OKAY;
8572 }
8573 
8574 /** adds a hole to the variable's global and local domain */
8576  SCIP_VAR* var, /**< problem variable */
8577  BMS_BLKMEM* blkmem, /**< block memory */
8578  SCIP_SET* set, /**< global SCIP settings */
8579  SCIP_STAT* stat, /**< problem statistics */
8580  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8581  SCIP_Real left, /**< left bound of open interval in new hole */
8582  SCIP_Real right, /**< right bound of open interval in new hole */
8583  SCIP_Bool* added /**< pointer to store whether the hole was added */
8584  )
8585 {
8586  SCIP_Real childnewleft;
8587  SCIP_Real childnewright;
8588 
8589  assert(var != NULL);
8590  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8591  assert(blkmem != NULL);
8592  assert(added != NULL);
8593 
8594  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8595 
8596  /* the interval should not be empty */
8597  assert(SCIPsetIsLT(set, left, right));
8598 
8599  /* the the interval bound should already be adjusted */
8600  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8601  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8602 
8603  /* the the interval should lay between the lower and upper bound */
8604  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8605  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8606 
8607  /* change bounds of attached variables */
8608  switch( SCIPvarGetStatus(var) )
8609  {
8611  if( var->data.original.transvar != NULL )
8612  {
8613  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8614  left, right, added) );
8615  }
8616  else
8617  {
8618  assert(set->stage == SCIP_STAGE_PROBLEM);
8619 
8620  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8621  if( *added )
8622  {
8623  SCIP_Bool localadded;
8624 
8625  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8626  }
8627  }
8628  break;
8629 
8630  case SCIP_VARSTATUS_COLUMN:
8631  case SCIP_VARSTATUS_LOOSE:
8632  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8633  if( *added )
8634  {
8635  SCIP_Bool localadded;
8636 
8637  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8638  }
8639  break;
8640 
8641  case SCIP_VARSTATUS_FIXED:
8642  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8643  return SCIP_INVALIDDATA;
8644 
8645  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8646  assert(var->data.aggregate.var != NULL);
8647 
8648  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8649  {
8650  /* a > 0 -> change lower bound of y */
8651  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8652  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8653  }
8654  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8655  {
8656  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8657  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8658  }
8659  else
8660  {
8661  SCIPerrorMessage("scalar is zero in aggregation\n");
8662  return SCIP_INVALIDDATA;
8663  }
8664  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8665  childnewleft, childnewright, added) );
8666  break;
8667 
8669  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8670  return SCIP_INVALIDDATA;
8671 
8672  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8673  assert(var->negatedvar != NULL);
8675  assert(var->negatedvar->negatedvar == var);
8676 
8677  childnewright = -left + var->data.negate.constant;
8678  childnewleft = -right + var->data.negate.constant;
8679 
8680  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8681  childnewleft, childnewright, added) );
8682  break;
8683 
8684  default:
8685  SCIPerrorMessage("unknown variable status\n");
8686  return SCIP_INVALIDDATA;
8687  }
8688 
8689  return SCIP_OKAY;
8690 }
8691 
8692 /** performs the current add of domain, changes all parents accordingly */
8693 static
8695  SCIP_VAR* var, /**< problem variable */
8696  BMS_BLKMEM* blkmem, /**< block memory */
8697  SCIP_SET* set, /**< global SCIP settings */
8698  SCIP_STAT* stat, /**< problem statistics */
8699  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8700  SCIP_Real left, /**< left bound of open interval in new hole */
8701  SCIP_Real right, /**< right bound of open interval in new hole */
8702  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8703  )
8704 {
8705  SCIP_VAR* parentvar;
8706  SCIP_Real newlb;
8707  SCIP_Real newub;
8708  int i;
8709 
8710  assert(var != NULL);
8711  assert(added != NULL);
8712  assert(blkmem != NULL);
8713 
8714  /* the interval should not be empty */
8715  assert(SCIPsetIsLT(set, left, right));
8716 
8717  /* the the interval bound should already be adjusted */
8718  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8719  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8720 
8721  /* the the interval should lay between the lower and upper bound */
8722  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8723  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8724 
8725  /* add hole to hole list */
8726  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8727 
8728  /* check if the hole is redundant */
8729  if( !(*added) )
8730  return SCIP_OKAY;
8731 
8732  /* current bounds */
8733  newlb = var->locdom.lb;
8734  newub = var->locdom.ub;
8735 
8736  /* merge domain holes */
8737  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8738 
8739  /* the bound should not be changed */
8740  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8741  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8742 
8743 #if 0
8744  /* issue bound change event */
8745  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8746  if( var->eventfilter != NULL )
8747  {
8748  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8749  }
8750 #endif
8751 
8752  /* process parent variables */
8753  for( i = 0; i < var->nparentvars; ++i )
8754  {
8755  SCIP_Real parentnewleft;
8756  SCIP_Real parentnewright;
8757  SCIP_Bool localadded;
8758 
8759  parentvar = var->parentvars[i];
8760  assert(parentvar != NULL);
8761 
8762  switch( SCIPvarGetStatus(parentvar) )
8763  {
8765  parentnewleft = left;
8766  parentnewright = right;
8767  break;
8768 
8769  case SCIP_VARSTATUS_COLUMN:
8770  case SCIP_VARSTATUS_LOOSE:
8771  case SCIP_VARSTATUS_FIXED:
8773  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8774  return SCIP_INVALIDDATA;
8775 
8776  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8777  assert(parentvar->data.aggregate.var == var);
8778 
8779  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8780  {
8781  /* a > 0 -> change upper bound of x */
8782  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8783  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8784  }
8785  else
8786  {
8787  /* a < 0 -> change lower bound of x */
8788  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8789 
8790  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8791  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8792  }
8793  break;
8794 
8795  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8796  assert(parentvar->negatedvar != NULL);
8797  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8798  assert(parentvar->negatedvar->negatedvar == parentvar);
8799 
8800  parentnewright = -left + parentvar->data.negate.constant;
8801  parentnewleft = -right + parentvar->data.negate.constant;
8802  break;
8803 
8804  default:
8805  SCIPerrorMessage("unknown variable status\n");
8806  return SCIP_INVALIDDATA;
8807  }
8808 
8809  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8810 
8811  /* perform hole added for parent variable */
8812  assert(blkmem != NULL);
8813  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8814  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8815  parentnewleft, parentnewright, &localadded) );
8816  assert(localadded);
8817  }
8818 
8819  return SCIP_OKAY;
8820 }
8821 
8822 /** adds a hole to the variable's current local domain */
8824  SCIP_VAR* var, /**< problem variable */
8825  BMS_BLKMEM* blkmem, /**< block memory */
8826  SCIP_SET* set, /**< global SCIP settings */
8827  SCIP_STAT* stat, /**< problem statistics */
8828  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8829  SCIP_Real left, /**< left bound of open interval in new hole */
8830  SCIP_Real right, /**< right bound of open interval in new hole */
8831  SCIP_Bool* added /**< pointer to store whether the hole was added */
8832  )
8833 {
8834  SCIP_Real childnewleft;
8835  SCIP_Real childnewright;
8836 
8837  assert(var != NULL);
8838 
8839  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8840 
8841  assert(set != NULL);
8842  assert(var->scip == set->scip);
8843  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8844  assert(blkmem != NULL);
8845  assert(added != NULL);
8846 
8847  /* the interval should not be empty */
8848  assert(SCIPsetIsLT(set, left, right));
8849 
8850  /* the the interval bound should already be adjusted */
8851  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8852  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8853 
8854  /* the the interval should lay between the lower and upper bound */
8855  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8856  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8857 
8858  /* change bounds of attached variables */
8859  switch( SCIPvarGetStatus(var) )
8860  {
8862  if( var->data.original.transvar != NULL )
8863  {
8864  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8865  left, right, added) );
8866  }
8867  else
8868  {
8869  assert(set->stage == SCIP_STAGE_PROBLEM);
8870  SCIPstatIncrement(stat, set, domchgcount);
8871  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8872  }
8873  break;
8874 
8875  case SCIP_VARSTATUS_COLUMN:
8876  case SCIP_VARSTATUS_LOOSE:
8877  SCIPstatIncrement(stat, set, domchgcount);
8878  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8879  break;
8880 
8881  case SCIP_VARSTATUS_FIXED:
8882  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8883  return SCIP_INVALIDDATA;
8884 
8885  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8886  assert(var->data.aggregate.var != NULL);
8887 
8888  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8889  {
8890  /* a > 0 -> change lower bound of y */
8891  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8892  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8893  }
8894  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8895  {
8896  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8897  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8898  }
8899  else
8900  {
8901  SCIPerrorMessage("scalar is zero in aggregation\n");
8902  return SCIP_INVALIDDATA;
8903  }
8904  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8905  childnewleft, childnewright, added) );
8906  break;
8907 
8909  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8910  return SCIP_INVALIDDATA;
8911 
8912  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8913  assert(var->negatedvar != NULL);
8915  assert(var->negatedvar->negatedvar == var);
8916 
8917  childnewright = -left + var->data.negate.constant;
8918  childnewleft = -right + var->data.negate.constant;
8919 
8920  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8921  break;
8922 
8923  default:
8924  SCIPerrorMessage("unknown variable status\n");
8925  return SCIP_INVALIDDATA;
8926  }
8927 
8928  return SCIP_OKAY;
8929 }
8930 
8931 /** resets the global and local bounds of original variable to their original values */
8933  SCIP_VAR* var, /**< problem variable */
8934  BMS_BLKMEM* blkmem, /**< block memory */
8935  SCIP_SET* set, /**< global SCIP settings */
8936  SCIP_STAT* stat /**< problem statistics */
8937  )
8938 {
8939  assert(var != NULL);
8940  assert(set != NULL);
8941  assert(var->scip == set->scip);
8942  assert(SCIPvarIsOriginal(var));
8943  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8944  * the transformed variable has been fixed */
8945  assert(SCIPvarGetTransVar(var) == NULL);
8946 
8947  /* copy the original bounds back to the global and local bounds */
8948  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8949  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8950  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8951  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8952 
8953  /* free the global and local holelists and duplicate the original ones */
8954  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8955  holelistFree(&var->glbdom.holelist, blkmem);
8956  holelistFree(&var->locdom.holelist, blkmem);
8957  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8958  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8959 
8960  return SCIP_OKAY;
8961 }
8962 
8963 /** issues a IMPLADDED event on the given variable */
8964 static
8966  SCIP_VAR* var, /**< problem variable to change */
8967  BMS_BLKMEM* blkmem, /**< block memory */
8968  SCIP_SET* set, /**< global SCIP settings */
8969  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8970  )
8971 {
8972  SCIP_EVENT* event;
8973 
8974  assert(var != NULL);
8975 
8976  /* issue IMPLADDED event on variable */
8977  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8978  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8979 
8980  return SCIP_OKAY;
8981 }
8982 
8983 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8984 static
8986  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8987  BMS_BLKMEM* blkmem, /**< block memory */
8988  SCIP_SET* set, /**< global SCIP settings */
8989  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8990  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8991  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8992  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8993  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8994  )
8995 {
8996  SCIP_Bool added;
8997 
8998  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8999  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9000  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9001  *
9002  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9003  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9004  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9005  * variable bound can be ignored.
9006  *
9007  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9008  * equivalence of the variables should be checked here.
9009  */
9010  if( var == vbvar )
9011  {
9012  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9013  * can be checked via the global bounds of the variable */
9014 #ifndef NDEBUG
9015  SCIP_Real lb;
9016  SCIP_Real ub;
9017 
9018  lb = SCIPvarGetLbGlobal(var);
9019  ub = SCIPvarGetUbGlobal(var);
9020 
9021  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9022  {
9023  if( vbcoef > 0.0 )
9024  {
9025  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9026  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9027  }
9028  else
9029  {
9030  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9031  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9032  }
9033  }
9034  else
9035  {
9036  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9037  if( vbcoef > 0.0 )
9038  {
9039  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9040  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9041  }
9042  else
9043  {
9044  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9045  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9046  }
9047  }
9048 #endif
9049  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9050  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9051 
9052  return SCIP_OKAY;
9053  }
9054 
9055  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9056  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9057 
9058  /* check variable bound on debugging solution */
9059  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9060 
9061  /* perform the addition */
9062  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9063  {
9064  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9065  }
9066  else
9067  {
9068  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9069  }
9070  var->closestvblpcount = -1;
9071 
9072  if( added )
9073  {
9074  /* issue IMPLADDED event */
9075  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9076  }
9077 
9078  return SCIP_OKAY;
9079 }
9080 
9081 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9082 static
9083 void checkImplic(
9084  SCIP_SET* set, /**< global SCIP settings */
9085  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9086  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9087  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9088  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9089  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9090  )
9091 {
9092  SCIP_Real impllb;
9093  SCIP_Real implub;
9094 
9095  assert(redundant != NULL);
9096  assert(infeasible != NULL);
9097 
9098  impllb = SCIPvarGetLbGlobal(implvar);
9099  implub = SCIPvarGetUbGlobal(implvar);
9100  if( impltype == SCIP_BOUNDTYPE_LOWER )
9101  {
9102  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9103  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9104  }
9105  else
9106  {
9107  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9108  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9109  }
9110 }
9111 
9112 /** applies the given implication, if it is not redundant */
9113 static
9115  BMS_BLKMEM* blkmem, /**< block memory */
9116  SCIP_SET* set, /**< global SCIP settings */
9117  SCIP_STAT* stat, /**< problem statistics */
9118  SCIP_PROB* transprob, /**< transformed problem */
9119  SCIP_PROB* origprob, /**< original problem */
9120  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9121  SCIP_REOPT* reopt, /**< reoptimization data structure */
9122  SCIP_LP* lp, /**< current LP data */
9123  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9124  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9125  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9126  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9127  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9128  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9129  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9130  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9131  )
9132 {
9133  SCIP_Real implub;
9134  SCIP_Real impllb;
9135 
9136  assert(infeasible != NULL);
9137 
9138  *infeasible = FALSE;
9139 
9140  implub = SCIPvarGetUbGlobal(implvar);
9141  impllb = SCIPvarGetLbGlobal(implvar);
9142  if( impltype == SCIP_BOUNDTYPE_LOWER )
9143  {
9144  if( SCIPsetIsFeasGT(set, implbound, implub) )
9145  {
9146  /* the implication produces a conflict: the problem is infeasible */
9147  *infeasible = TRUE;
9148  }
9149  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9150  {
9151  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9152  * with the local bound, in this case we need to store the bound change as pending bound change
9153  */
9154  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9155  {
9156  assert(tree != NULL);
9157  assert(transprob != NULL);
9158  assert(SCIPprobIsTransformed(transprob));
9159 
9160  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9161  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9162  }
9163  else
9164  {
9165  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9166  }
9167 
9168  if( nbdchgs != NULL )
9169  (*nbdchgs)++;
9170  }
9171  }
9172  else
9173  {
9174  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9175  {
9176  /* the implication produces a conflict: the problem is infeasible */
9177  *infeasible = TRUE;
9178  }
9179  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9180  {
9181  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9182  * with the local bound, in this case we need to store the bound change as pending bound change
9183  */
9184  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9185  {
9186  assert(tree != NULL);
9187  assert(transprob != NULL);
9188  assert(SCIPprobIsTransformed(transprob));
9189 
9190  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9191  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9192  }
9193  else
9194  {
9195  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9196  }
9197 
9198  if( nbdchgs != NULL )
9199  (*nbdchgs)++;
9200  }
9201  }
9202 
9203  return SCIP_OKAY;
9204 }
9205 
9206 /** actually performs the addition of an implication to the variable's implication arrays,
9207  * and adds the corresponding implication or variable bound to the implied variable;
9208  * if the implication is conflicting, the variable is fixed to the opposite value;
9209  * if the variable is already fixed to the given value, the implication is performed immediately;
9210  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9211  */
9212 static
9214  SCIP_VAR* var, /**< problem variable */
9215  BMS_BLKMEM* blkmem, /**< block memory */
9216  SCIP_SET* set, /**< global SCIP settings */
9217  SCIP_STAT* stat, /**< problem statistics */
9218  SCIP_PROB* transprob, /**< transformed problem */
9219  SCIP_PROB* origprob, /**< original problem */
9220  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9221  SCIP_REOPT* reopt, /**< reoptimization data structure */
9222  SCIP_LP* lp, /**< current LP data */
9223  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9224  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9225  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9226  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9227  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9228  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9229  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9230  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9231  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9232  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9233  SCIP_Bool* added /**< pointer to store whether an implication was added */
9234  )
9235 {
9236  SCIP_Bool redundant;
9237  SCIP_Bool conflict;
9238 
9239  assert(var != NULL);
9240  assert(SCIPvarIsActive(var));
9242  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9243  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9244  assert(infeasible != NULL);
9245  assert(added != NULL);
9246 
9247  /* check implication on debugging solution */
9248  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9249 
9250  *infeasible = FALSE;
9251  *added = FALSE;
9252 
9253  /* check, if the implication is redundant or infeasible */
9254  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9255  assert(!redundant || !conflict);
9256  if( redundant )
9257  return SCIP_OKAY;
9258 
9259  if( var == implvar )
9260  {
9261  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9262  * x == varfixing => x < 0 or x > 1
9263  */
9264  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9265  conflict = TRUE;
9266  else
9267  {
9268  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9269  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9270  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9271  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9272  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9273  if( !conflict )
9274  return SCIP_OKAY;
9275  }
9276  }
9277 
9278  /* check, if the variable is already fixed */
9279  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9280  {
9281  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9282  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9283  {
9284  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9285  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9286  }
9287  return SCIP_OKAY;
9288  }
9289 
9290  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9291  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9292 
9293  if( !conflict )
9294  {
9295  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9296 
9297  if( SCIPvarIsBinary(implvar) )
9298  {
9299  SCIP_VAR* vars[2];
9300  SCIP_Bool vals[2];
9301 
9302  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9303  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9304 
9305  vars[0] = var;
9306  vars[1] = implvar;
9307  vals[0] = varfixing;
9308  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9309 
9310  /* add the clique to the clique table */
9311  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9312  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9313 
9314  if( !conflict )
9315  return SCIP_OKAY;
9316  }
9317  else
9318  {
9319  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9320  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9321  SCIPvarGetName(var), varfixing,
9322  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9323  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9324  isshortcut, &conflict, added) );
9325  }
9326  }
9327  assert(!conflict || !(*added));
9328 
9329  /* on conflict, fix the variable to the opposite value */
9330  if( conflict )
9331  {
9332  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9333 
9334  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9335  * with the local bound, in this case we need to store the bound change as pending bound change
9336  */
9337  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9338  {
9339  assert(tree != NULL);
9340  assert(transprob != NULL);
9341  assert(SCIPprobIsTransformed(transprob));
9342 
9343  if( varfixing )
9344  {
9345  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9346  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9347  }
9348  else
9349  {
9350  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9351  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9352  }
9353  }
9354  else
9355  {
9356  if( varfixing )
9357  {
9358  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9359  }
9360  else
9361  {
9362  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9363  }
9364  }
9365  if( nbdchgs != NULL )
9366  (*nbdchgs)++;
9367 
9368  return SCIP_OKAY;
9369  }
9370  else if( *added )
9371  {
9372  /* issue IMPLADDED event */
9373  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9374  }
9375  else
9376  {
9377  /* the implication was redundant: the inverse is also redundant */
9378  return SCIP_OKAY;
9379  }
9380 
9381  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9382 
9383  /* check, whether implied variable is binary */
9384  if( !SCIPvarIsBinary(implvar) )
9385  {
9386  SCIP_Real lb;
9387  SCIP_Real ub;
9388 
9389  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9390  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9391  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9392  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9393  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9394  * for numerical reasons, ignore variable bounds with large absolute coefficient
9395  */
9396  lb = SCIPvarGetLbGlobal(implvar);
9397  ub = SCIPvarGetUbGlobal(implvar);
9398  if( impltype == SCIP_BOUNDTYPE_UPPER )
9399  {
9400  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9401  {
9402  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9403  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9404  }
9405  }
9406  else
9407  {
9408  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9409  {
9410  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9411  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9412  }
9413  }
9414  }
9415 
9416  return SCIP_OKAY;
9417 }
9418 
9419 /** adds transitive closure for binary implication x = a -> y = b */
9420 static
9422  SCIP_VAR* var, /**< problem variable */
9423  BMS_BLKMEM* blkmem, /**< block memory */
9424  SCIP_SET* set, /**< global SCIP settings */
9425  SCIP_STAT* stat, /**< problem statistics */
9426  SCIP_PROB* transprob, /**< transformed problem */
9427  SCIP_PROB* origprob, /**< original problem */
9428  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9429  SCIP_REOPT* reopt, /**< reoptimization data structure */
9430  SCIP_LP* lp, /**< current LP data */
9431  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9432  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9433  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9434  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9435  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9436  SCIP_Bool implvarfixing, /**< fixing b in implication */
9437  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9438  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9439  )
9440 {
9441  SCIP_VAR** implvars;
9442  SCIP_BOUNDTYPE* impltypes;
9443  SCIP_Real* implbounds;
9444  int nimpls;
9445  int i;
9446 
9447  *infeasible = FALSE;
9448 
9449  /* binary variable: implications of implvar */
9450  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9451  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9452  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9453  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9454 
9455  /* if variable has too many implications, the implication graph may become too dense */
9456  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9457 
9458  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9459  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9460  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9461  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9462  * only thing that can happen is that we add the same implication twice - this does no harm
9463  */
9464  while ( i >= 0 && !(*infeasible) )
9465  {
9466  SCIP_Bool added;
9467 
9468  assert(implvars[i] != implvar);
9469 
9470  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9471  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9472  */
9473  if( SCIPvarIsActive(implvars[i]) )
9474  {
9475  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9476  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9477  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9478  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9479  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9480  }
9481  --i;
9482  }
9483 
9484  return SCIP_OKAY;
9485 }
9486 
9487 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9488  * implication to the variable's implication list;
9489  * if the implication is conflicting, the variable is fixed to the opposite value;
9490  * if the variable is already fixed to the given value, the implication is performed immediately;
9491  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9492  */
9493 static
9495  SCIP_VAR* var, /**< problem variable */
9496  BMS_BLKMEM* blkmem, /**< block memory */
9497  SCIP_SET* set, /**< global SCIP settings */
9498  SCIP_STAT* stat, /**< problem statistics */
9499  SCIP_PROB* transprob, /**< transformed problem */
9500  SCIP_PROB* origprob, /**< original problem */
9501  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9502  SCIP_REOPT* reopt, /**< reoptimization data structure */
9503  SCIP_LP* lp, /**< current LP data */
9504  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9505  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9506  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9507  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9508  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9509  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9510  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9511  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9512  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9513  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9514  )
9515 {
9516  SCIP_Bool added;
9517 
9518  assert(var != NULL);
9519  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9520  assert(SCIPvarIsActive(var));
9521  assert(implvar != NULL);
9522  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9523  assert(infeasible != NULL);
9524 
9525  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9526  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9527  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9528 
9529  if( *infeasible || var == implvar || !transitive || !added )
9530  return SCIP_OKAY;
9531 
9532  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9533 
9534  /* add transitive closure */
9535  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9536  {
9537  SCIP_Bool implvarfixing;
9538 
9539  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9540 
9541  /* binary variable: implications of implvar */
9542  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9543  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9544 
9545  /* inverse implication */
9546  if( !(*infeasible) )
9547  {
9548  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9549  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9550  }
9551  }
9552  else
9553  {
9554  /* non-binary variable: variable lower bounds of implvar */
9555  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9556  {
9557  SCIP_VAR** vlbvars;
9558  SCIP_Real* vlbcoefs;
9559  SCIP_Real* vlbconstants;
9560  int nvlbvars;
9561  int i;
9562 
9563  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9564  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9565  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9566  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9567 
9568  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9569  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9570  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9571  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9572  * is that we add the same implication twice - this does no harm
9573  */
9574  i = nvlbvars-1;
9575  while ( i >= 0 && !(*infeasible) )
9576  {
9577  assert(vlbvars[i] != implvar);
9578  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9579 
9580  /* we have x == varfixing -> y <= b and y >= c*z + d:
9581  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9582  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9583  *
9584  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9585  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9586  * aggregation variable (the one which will stay active);
9587  *
9588  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9589  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9590  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9591  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9592  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9593  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9594  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9595  * have to explicitly check that the active variable has not a variable status
9596  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9597  */
9598  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9599  {
9600  SCIP_Real vbimplbound;
9601 
9602  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9603  if( vlbcoefs[i] >= 0.0 )
9604  {
9605  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9606  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9607  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9608  infeasible, nbdchgs, &added) );
9609  }
9610  else
9611  {
9612  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9613  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9614  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9615  infeasible, nbdchgs, &added) );
9616  }
9617  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9618  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9619  }
9620  --i;
9621  }
9622  }
9623 
9624  /* non-binary variable: variable upper bounds of implvar */
9625  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9626  {
9627  SCIP_VAR** vubvars;
9628  SCIP_Real* vubcoefs;
9629  SCIP_Real* vubconstants;
9630  int nvubvars;
9631  int i;
9632 
9633  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9634  vubvars = SCIPvboundsGetVars(implvar->vubs);
9635  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9636  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9637 
9638  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9639  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9640  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9641  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9642  * is that we add the same implication twice - this does no harm
9643  */
9644  i = nvubvars-1;
9645  while ( i >= 0 && !(*infeasible) )
9646  {
9647  assert(vubvars[i] != implvar);
9648  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9649 
9650  /* we have x == varfixing -> y >= b and y <= c*z + d:
9651  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9652  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9653  *
9654  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9655  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9656  * aggregation variable (the one which will stay active);
9657  *
9658  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9659  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9660  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9661  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9662  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9663  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9664  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9665  * have to explicitly check that the active variable has not a variable status
9666  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9667  */
9668  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9669  {
9670  SCIP_Real vbimplbound;
9671 
9672  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9673  if( vubcoefs[i] >= 0.0 )
9674  {
9675  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9676  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9677  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9678  infeasible, nbdchgs, &added) );
9679  }
9680  else
9681  {
9682  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9683  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9684  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9685  infeasible, nbdchgs, &added) );
9686  }
9687  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9688  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9689  }
9690  --i;
9691  }
9692  }
9693  }
9694 
9695  return SCIP_OKAY;
9696 }
9697 
9698 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9699  * if z is binary, the corresponding valid implication for z is also added;
9700  * improves the global bounds of the variable and the vlb variable if possible
9701  */
9703  SCIP_VAR* var, /**< problem variable */
9704  BMS_BLKMEM* blkmem, /**< block memory */
9705  SCIP_SET* set, /**< global SCIP settings */
9706  SCIP_STAT* stat, /**< problem statistics */
9707  SCIP_PROB* transprob, /**< transformed problem */
9708  SCIP_PROB* origprob, /**< original problem */
9709  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9710  SCIP_REOPT* reopt, /**< reoptimization data structure */
9711  SCIP_LP* lp, /**< current LP data */
9712  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9713  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9714  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9715  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9716  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9717  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9718  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9719  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9720  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9721  )
9722 {
9723  assert(var != NULL);
9724  assert(set != NULL);
9725  assert(var->scip == set->scip);
9726  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9727  assert(infeasible != NULL);
9728 
9729  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9730 
9731  *infeasible = FALSE;
9732  if( nbdchgs != NULL )
9733  *nbdchgs = 0;
9734 
9735  switch( SCIPvarGetStatus(var) )
9736  {
9738  assert(var->data.original.transvar != NULL);
9739  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9740  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9741  break;
9742 
9743  case SCIP_VARSTATUS_COLUMN:
9744  case SCIP_VARSTATUS_LOOSE:
9745  case SCIP_VARSTATUS_FIXED:
9746  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9747  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9748  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9749 
9750  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9751  if( SCIPsetIsZero(set, vlbcoef) )
9752  {
9753  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9754  *infeasible = TRUE;
9755  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9756  {
9757  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9758  * with the local bound, in this case we need to store the bound change as pending bound change
9759  */
9760  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9761  {
9762  assert(tree != NULL);
9763  assert(transprob != NULL);
9764  assert(SCIPprobIsTransformed(transprob));
9765 
9766  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9767  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9768  }
9769  else
9770  {
9771  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9772  }
9773 
9774  if( nbdchgs != NULL )
9775  (*nbdchgs)++;
9776  }
9777  }
9778  else if( SCIPvarIsActive(vlbvar) )
9779  {
9780  SCIP_Real xlb;
9781  SCIP_Real xub;
9782  SCIP_Real zlb;
9783  SCIP_Real zub;
9784  SCIP_Real minvlb;
9785  SCIP_Real maxvlb;
9786 
9788  assert(vlbcoef != 0.0);
9789 
9790  minvlb = -SCIPsetInfinity(set);
9791  maxvlb = SCIPsetInfinity(set);
9792 
9793  xlb = SCIPvarGetLbGlobal(var);
9794  xub = SCIPvarGetUbGlobal(var);
9795  zlb = SCIPvarGetLbGlobal(vlbvar);
9796  zub = SCIPvarGetUbGlobal(vlbvar);
9797 
9798  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9799  if( vlbcoef >= 0.0 )
9800  {
9801  SCIP_Real newzub;
9802 
9803  if( !SCIPsetIsInfinity(set, xub) )
9804  {
9805  /* x >= b*z + d -> z <= (x-d)/b */
9806  newzub = (xub - vlbconstant)/vlbcoef;
9807 
9808  /* return if the new bound is less than -infinity */
9809  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9810  return SCIP_OKAY;
9811 
9812  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9813  {
9814  *infeasible = TRUE;
9815  return SCIP_OKAY;
9816  }
9817  if( SCIPsetIsFeasLT(set, newzub, zub) )
9818  {
9819  /* bound might be adjusted due to integrality condition */
9820  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9821 
9822  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9823  * with the local bound, in this case we need to store the bound change as pending bound change
9824  */
9825  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9826  {
9827  assert(tree != NULL);
9828  assert(transprob != NULL);
9829  assert(SCIPprobIsTransformed(transprob));
9830 
9831  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9832  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9833  }
9834  else
9835  {
9836  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9837  }
9838  zub = newzub;
9839 
9840  if( nbdchgs != NULL )
9841  (*nbdchgs)++;
9842  }
9843  maxvlb = vlbcoef * zub + vlbconstant;
9844  if( !SCIPsetIsInfinity(set, -zlb) )
9845  minvlb = vlbcoef * zlb + vlbconstant;
9846  }
9847  else
9848  {
9849  if( !SCIPsetIsInfinity(set, zub) )
9850  maxvlb = vlbcoef * zub + vlbconstant;
9851  if( !SCIPsetIsInfinity(set, -zlb) )
9852  minvlb = vlbcoef * zlb + vlbconstant;
9853  }
9854  }
9855  else
9856  {
9857  SCIP_Real newzlb;
9858 
9859  if( !SCIPsetIsInfinity(set, xub) )
9860  {
9861  /* x >= b*z + d -> z >= (x-d)/b */
9862  newzlb = (xub - vlbconstant)/vlbcoef;
9863 
9864  /* return if the new bound is larger than infinity */
9865  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9866  return SCIP_OKAY;
9867 
9868  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9869  {
9870  *infeasible = TRUE;
9871  return SCIP_OKAY;
9872  }
9873  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9874  {
9875  /* bound might be adjusted due to integrality condition */
9876  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9877 
9878  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9879  * with the local bound, in this case we need to store the bound change as pending bound change
9880  */
9881  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9882  {
9883  assert(tree != NULL);
9884  assert(transprob != NULL);
9885  assert(SCIPprobIsTransformed(transprob));
9886 
9887  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9888  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9889  }
9890  else
9891  {
9892  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9893  }
9894  zlb = newzlb;
9895 
9896  if( nbdchgs != NULL )
9897  (*nbdchgs)++;
9898  }
9899  maxvlb = vlbcoef * zlb + vlbconstant;
9900  if( !SCIPsetIsInfinity(set, zub) )
9901  minvlb = vlbcoef * zub + vlbconstant;
9902  }
9903  else
9904  {
9905  if( !SCIPsetIsInfinity(set, -zlb) )
9906  maxvlb = vlbcoef * zlb + vlbconstant;
9907  if( !SCIPsetIsInfinity(set, zub) )
9908  minvlb = vlbcoef * zub + vlbconstant;
9909  }
9910  }
9911  if( maxvlb < minvlb )
9912  maxvlb = minvlb;
9913 
9914  /* adjust bounds due to integrality of variable */
9915  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9916  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9917 
9918  /* check bounds for feasibility */
9919  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9920  {
9921  *infeasible = TRUE;
9922  return SCIP_OKAY;
9923  }
9924  /* improve global lower bound of variable */
9925  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9926  {
9927  /* bound might be adjusted due to integrality condition */
9928  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9929 
9930  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9931  * with the local bound, in this case we need to store the bound change as pending bound change
9932  */
9933  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9934  {
9935  assert(tree != NULL);
9936  assert(transprob != NULL);
9937  assert(SCIPprobIsTransformed(transprob));
9938 
9939  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9940  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9941  }
9942  else
9943  {
9944  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9945  }
9946  xlb = minvlb;
9947 
9948  if( nbdchgs != NULL )
9949  (*nbdchgs)++;
9950  }
9951  minvlb = xlb;
9952 
9953  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9954  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9955  {
9956  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9957  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9958  */
9959 
9960  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9961 
9962  if( vlbcoef >= 0.0 )
9963  {
9964  vlbcoef = maxvlb - minvlb;
9965  vlbconstant = minvlb;
9966  }
9967  else
9968  {
9969  vlbcoef = minvlb - maxvlb;
9970  vlbconstant = maxvlb;
9971  }
9972  }
9973 
9974  /* add variable bound to the variable bounds list */
9975  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9976  {
9977  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9978  assert(!SCIPsetIsZero(set, vlbcoef));
9979 
9980  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9981  * list, thereby also adding the variable bound (or implication) to the other variable
9982  */
9983  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9984  {
9985  /* add corresponding implication:
9986  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9987  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9988  */
9989  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9990  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9991  infeasible, nbdchgs) );
9992  }
9993  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9994  {
9995  /* add corresponding implication:
9996  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9997  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9998  */
9999  SCIP_Real implbound;
10000  implbound = -vlbconstant/vlbcoef;
10001 
10002  /* tighten the implication bound if the variable is integer */
10003  if( SCIPvarIsIntegral(vlbvar) )
10004  {
10005  if( vlbcoef >= 0 )
10006  implbound = SCIPsetFloor(set, implbound);
10007  else
10008  implbound = SCIPsetCeil(set, implbound);
10009  }
10010  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10011  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10012  implbound, transitive, infeasible, nbdchgs) );
10013  }
10014  else
10015  {
10016  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10017  }
10018  }
10019  }
10020  break;
10021 
10023  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10024  * y <= b/a * z + (d-c)/a, if a < 0
10025  */
10026  assert(var->data.aggregate.var != NULL);
10027  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10028  {
10029  /* a > 0 -> add variable lower bound */
10030  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10031  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10032  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10033  }
10034  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10035  {
10036  /* a < 0 -> add variable upper bound */
10037  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10038  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10039  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10040  }
10041  else
10042  {
10043  SCIPerrorMessage("scalar is zero in aggregation\n");
10044  return SCIP_INVALIDDATA;
10045  }
10046  break;
10047 
10049  /* nothing to do here */
10050  break;
10051 
10053  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10054  assert(var->negatedvar != NULL);
10056  assert(var->negatedvar->negatedvar == var);
10057  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10058  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10059  nbdchgs) );
10060  break;
10061 
10062  default:
10063  SCIPerrorMessage("unknown variable status\n");
10064  return SCIP_INVALIDDATA;
10065  }
10066 
10067  return SCIP_OKAY;
10068 }
10069 
10070 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10071  * if z is binary, the corresponding valid implication for z is also added;
10072  * updates the global bounds of the variable and the vub variable correspondingly
10073  */
10075  SCIP_VAR* var, /**< problem variable */
10076  BMS_BLKMEM* blkmem, /**< block memory */
10077  SCIP_SET* set, /**< global SCIP settings */
10078  SCIP_STAT* stat, /**< problem statistics */
10079  SCIP_PROB* transprob, /**< transformed problem */
10080  SCIP_PROB* origprob, /**< original problem */
10081  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10082  SCIP_REOPT* reopt, /**< reoptimization data structure */
10083  SCIP_LP* lp, /**< current LP data */
10084  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10085  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10086  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10087  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10088  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10089  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10090  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10091  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10092  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10093  )
10094 {
10095  assert(var != NULL);
10096  assert(set != NULL);
10097  assert(var->scip == set->scip);
10098  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10099  assert(infeasible != NULL);
10100 
10101  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10102 
10103  *infeasible = FALSE;
10104  if( nbdchgs != NULL )
10105  *nbdchgs = 0;
10106 
10107  switch( SCIPvarGetStatus(var) )
10108  {
10110  assert(var->data.original.transvar != NULL);
10111  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10112  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10113  break;
10114 
10115  case SCIP_VARSTATUS_COLUMN:
10116  case SCIP_VARSTATUS_LOOSE:
10117  case SCIP_VARSTATUS_FIXED:
10118  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10119  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10120  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10121  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10122 
10123  /* if the vub coefficient is zero, just update the upper bound of the variable */
10124  if( SCIPsetIsZero(set, vubcoef) )
10125  {
10126  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10127  *infeasible = TRUE;
10128  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10129  {
10130  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10131  * with the local bound, in this case we need to store the bound change as pending bound change
10132  */
10133  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10134  {
10135  assert(tree != NULL);
10136  assert(transprob != NULL);
10137  assert(SCIPprobIsTransformed(transprob));
10138 
10139  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10140  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10141  }
10142  else
10143  {
10144  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10145  }
10146 
10147  if( nbdchgs != NULL )
10148  (*nbdchgs)++;
10149  }
10150  }
10151  else if( SCIPvarIsActive(vubvar) )
10152  {
10153  SCIP_Real xlb;
10154  SCIP_Real xub;
10155  SCIP_Real zlb;
10156  SCIP_Real zub;
10157  SCIP_Real minvub;
10158  SCIP_Real maxvub;
10159 
10161  assert(vubcoef != 0.0);
10162 
10163  minvub = -SCIPsetInfinity(set);
10164  maxvub = SCIPsetInfinity(set);
10165 
10166  xlb = SCIPvarGetLbGlobal(var);
10167  xub = SCIPvarGetUbGlobal(var);
10168  zlb = SCIPvarGetLbGlobal(vubvar);
10169  zub = SCIPvarGetUbGlobal(vubvar);
10170 
10171  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10172  if( vubcoef >= 0.0 )
10173  {
10174  SCIP_Real newzlb;
10175 
10176  if( !SCIPsetIsInfinity(set, -xlb) )
10177  {
10178  /* x <= b*z + d -> z >= (x-d)/b */
10179  newzlb = (xlb - vubconstant)/vubcoef;
10180  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10181  {
10182  *infeasible = TRUE;
10183  return SCIP_OKAY;
10184  }
10185  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10186  {
10187  /* bound might be adjusted due to integrality condition */
10188  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10189 
10190  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10191  * with the local bound, in this case we need to store the bound change as pending bound change
10192  */
10193  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10194  {
10195  assert(tree != NULL);
10196  assert(transprob != NULL);
10197  assert(SCIPprobIsTransformed(transprob));
10198 
10199  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10200  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10201  }
10202  else
10203  {
10204  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10205  }
10206  zlb = newzlb;
10207 
10208  if( nbdchgs != NULL )
10209  (*nbdchgs)++;
10210  }
10211  minvub = vubcoef * zlb + vubconstant;
10212  if( !SCIPsetIsInfinity(set, zub) )
10213  maxvub = vubcoef * zub + vubconstant;
10214  }
10215  else
10216  {
10217  if( !SCIPsetIsInfinity(set, zub) )
10218  maxvub = vubcoef * zub + vubconstant;
10219  if( !SCIPsetIsInfinity(set, -zlb) )
10220  minvub = vubcoef * zlb + vubconstant;
10221  }
10222  }
10223  else
10224  {
10225  SCIP_Real newzub;
10226 
10227  if( !SCIPsetIsInfinity(set, -xlb) )
10228  {
10229  /* x <= b*z + d -> z <= (x-d)/b */
10230  newzub = (xlb - vubconstant)/vubcoef;
10231  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10232  {
10233  *infeasible = TRUE;
10234  return SCIP_OKAY;
10235  }
10236  if( SCIPsetIsFeasLT(set, newzub, zub) )
10237  {
10238  /* bound might be adjusted due to integrality condition */
10239  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10240 
10241  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10242  * with the local bound, in this case we need to store the bound change as pending bound change
10243  */
10244  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10245  {
10246  assert(tree != NULL);
10247  assert(transprob != NULL);
10248  assert(SCIPprobIsTransformed(transprob));
10249 
10250  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10251  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10252  }
10253  else
10254  {
10255  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10256  }
10257  zub = newzub;
10258 
10259  if( nbdchgs != NULL )
10260  (*nbdchgs)++;
10261  }
10262  minvub = vubcoef * zub + vubconstant;
10263  if( !SCIPsetIsInfinity(set, -zlb) )
10264  maxvub = vubcoef * zlb + vubconstant;
10265  }
10266  else
10267  {
10268  if( !SCIPsetIsInfinity(set, zub) )
10269  minvub = vubcoef * zub + vubconstant;
10270  if( !SCIPsetIsInfinity(set, -zlb) )
10271  maxvub = vubcoef * zlb + vubconstant;
10272  }
10273  }
10274  if( minvub > maxvub )
10275  minvub = maxvub;
10276 
10277  /* adjust bounds due to integrality of vub variable */
10278  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10279  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10280 
10281  /* check bounds for feasibility */
10282  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10283  {
10284  *infeasible = TRUE;
10285  return SCIP_OKAY;
10286  }
10287 
10288  /* improve global upper bound of variable */
10289  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10290  {
10291  /* bound might be adjusted due to integrality condition */
10292  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10293 
10294  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10295  * with the local bound, in this case we need to store the bound change as pending bound change
10296  */
10297  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10298  {
10299  assert(tree != NULL);
10300  assert(transprob != NULL);
10301  assert(SCIPprobIsTransformed(transprob));
10302 
10303  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10304  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10305  }
10306  else
10307  {
10308  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10309  }
10310  xub = maxvub;
10311 
10312  if( nbdchgs != NULL )
10313  (*nbdchgs)++;
10314  }
10315  maxvub = xub;
10316 
10317  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10318  if( SCIPvarIsBinary(vubvar) )
10319  {
10320  /* b > 0: x <= (maxvub - minvub) * z + minvub
10321  * b < 0: x <= (minvub - maxvub) * z + maxvub
10322  */
10323 
10324  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10325 
10326  if( vubcoef >= 0.0 )
10327  {
10328  vubcoef = maxvub - minvub;
10329  vubconstant = minvub;
10330  }
10331  else
10332  {
10333  vubcoef = minvub - maxvub;
10334  vubconstant = maxvub;
10335  }
10336  }
10337 
10338  /* add variable bound to the variable bounds list */
10339  if( SCIPsetIsFeasLT(set, minvub, xub) )
10340  {
10341  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10342  assert(!SCIPsetIsZero(set, vubcoef));
10343 
10344  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10345  * list, thereby also adding the variable bound (or implication) to the other variable
10346  */
10347  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10348  {
10349  /* add corresponding implication:
10350  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10351  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10352  */
10353  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10354  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10355  infeasible, nbdchgs) );
10356  }
10357  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10358  {
10359  /* add corresponding implication:
10360  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10361  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10362  */
10363  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10364  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10365  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10366  }
10367  else
10368  {
10369  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10370  }
10371  }
10372  }
10373  break;
10374 
10376  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10377  * y >= b/a * z + (d-c)/a, if a < 0
10378  */
10379  assert(var->data.aggregate.var != NULL);
10380  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10381  {
10382  /* a > 0 -> add variable upper bound */
10383  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10384  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10385  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10386  }
10387  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10388  {
10389  /* a < 0 -> add variable lower bound */
10390  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10391  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10392  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10393  }
10394  else
10395  {
10396  SCIPerrorMessage("scalar is zero in aggregation\n");
10397  return SCIP_INVALIDDATA;
10398  }
10399  break;
10400 
10402  /* nothing to do here */
10403  break;
10404 
10406  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10407  assert(var->negatedvar != NULL);
10409  assert(var->negatedvar->negatedvar == var);
10410  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10411  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10412  nbdchgs) );
10413  break;
10414 
10415  default:
10416  SCIPerrorMessage("unknown variable status\n");
10417  return SCIP_INVALIDDATA;
10418  }
10419 
10420  return SCIP_OKAY;
10421 }
10422 
10423 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10424  * also adds the corresponding implication or variable bound to the implied variable;
10425  * if the implication is conflicting, the variable is fixed to the opposite value;
10426  * if the variable is already fixed to the given value, the implication is performed immediately;
10427  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10428  */
10430  SCIP_VAR* var, /**< problem variable */
10431  BMS_BLKMEM* blkmem, /**< block memory */
10432  SCIP_SET* set, /**< global SCIP settings */
10433  SCIP_STAT* stat, /**< problem statistics */
10434  SCIP_PROB* transprob, /**< transformed problem */
10435  SCIP_PROB* origprob, /**< original problem */
10436  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10437  SCIP_REOPT* reopt, /**< reoptimization data structure */
10438  SCIP_LP* lp, /**< current LP data */
10439  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10440  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10441  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10442  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10443  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10444  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10445  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10446  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10447  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10448  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10449  )
10450 {
10451  assert(var != NULL);
10452  assert(set != NULL);
10453  assert(var->scip == set->scip);
10454  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10455  assert(infeasible != NULL);
10456 
10457  *infeasible = FALSE;
10458  if( nbdchgs != NULL )
10459  *nbdchgs = 0;
10460 
10461  switch( SCIPvarGetStatus(var) )
10462  {
10464  assert(var->data.original.transvar != NULL);
10465  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10466  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10467  nbdchgs) );
10468  break;
10469 
10470  case SCIP_VARSTATUS_COLUMN:
10471  case SCIP_VARSTATUS_LOOSE:
10472  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10473  * the variable, the implication can be applied directly;
10474  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10475  */
10476  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10477  {
10478  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10479  {
10480  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10481  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10482  }
10483  }
10484  else
10485  {
10486  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10487  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10488  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10489  {
10490  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10491  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10492  }
10493  }
10494  break;
10495 
10496  case SCIP_VARSTATUS_FIXED:
10497  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10498  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10499  {
10500  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10501  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10502  }
10503  break;
10504 
10506  /* implication added for x == 1:
10507  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10508  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10509  * implication added for x == 0:
10510  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10511  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10512  *
10513  * use only binary variables z
10514  */
10515  assert(var->data.aggregate.var != NULL);
10516  if( SCIPvarIsBinary(var->data.aggregate.var) )
10517  {
10518  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10519  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10520 
10521  if( var->data.aggregate.scalar > 0 )
10522  {
10523  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10524  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10525  nbdchgs) );
10526  }
10527  else
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  }
10534  break;
10535 
10537  /* nothing to do here */
10538  break;
10539 
10541  /* implication added for x == 1:
10542  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10543  * implication added for x == 0:
10544  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10545  */
10546  assert(var->negatedvar != NULL);
10548  assert(var->negatedvar->negatedvar == var);
10549  assert(SCIPvarIsBinary(var->negatedvar));
10550 
10552  {
10553  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10554  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10555  }
10556  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10557  else
10558  {
10559  /* if the implied variable is of binary type exchange the variables */
10560  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10561  {
10562  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10563  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10564  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10565  infeasible, nbdchgs) );
10566  }
10567  else
10568  {
10569  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10570  * implication as variable bounds
10571  */
10572 
10573  /* add variable lower bound on the negation of var */
10574  if( varfixing )
10575  {
10576  /* (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
10577  * as variable lower bound
10578  */
10579  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10580  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10581  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10582  }
10583  else
10584  {
10585  /* (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
10586  * as variable upper bound
10587  */
10588  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10589  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10590  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10591  }
10592 
10593  /* add variable bound on implvar */
10594  if( impltype == SCIP_BOUNDTYPE_UPPER )
10595  {
10596  /* (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
10597  * as variable upper bound
10598  */
10599  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10600  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10601  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10602  }
10603  else
10604  {
10605  /* (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
10606  * as variable upper bound
10607  */
10608  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10609  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10610  transitive, infeasible, nbdchgs) );
10611  }
10612  }
10613  }
10614  break;
10615 
10616  default:
10617  SCIPerrorMessage("unknown variable status\n");
10618  return SCIP_INVALIDDATA;
10619  }
10620 
10621  return SCIP_OKAY;
10622 }
10623 
10624 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10625  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10626  * both variables must be active, variable x must be binary
10627  */
10629  SCIP_VAR* var, /**< problem variable x */
10630  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10631  SCIP_VAR* implvar, /**< variable y to search for */
10632  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10633  )
10634 {
10635  assert(var != NULL);
10636  assert(implvar != NULL);
10637  assert(SCIPvarIsActive(var));
10638  assert(SCIPvarIsActive(implvar));
10639  assert(SCIPvarIsBinary(var));
10640 
10641  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10642 }
10643 
10644 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10645  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10646  * both variables must be active binary variables
10647  */
10649  SCIP_VAR* var, /**< problem variable x */
10650  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10651  SCIP_VAR* implvar, /**< variable y to search for */
10652  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10653  )
10654 {
10655  assert(SCIPvarIsBinary(implvar));
10656 
10657  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10658 }
10659 
10660 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10662  SCIP_VAR* var, /**< problem variable */
10663  BMS_BLKMEM* blkmem, /**< block memory */
10664  SCIP_SET* set, /**< global SCIP settings */
10665  SCIP_STAT* stat, /**< problem statistics */
10666  SCIP_PROB* transprob, /**< transformed problem */
10667  SCIP_PROB* origprob, /**< original problem */
10668  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10669  SCIP_REOPT* reopt, /**< reoptimization data structure */
10670  SCIP_LP* lp, /**< current LP data */
10671  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10672  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10673  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10674  SCIP_Bool value, /**< value to fix variable to */
10675  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10676  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10677  )
10678 {
10679  assert(var != NULL);
10680  assert(set != NULL);
10681  assert(var->scip == set->scip);
10682  assert(infeasible != NULL);
10683 
10684  *infeasible = FALSE;
10685 
10686  if( value == FALSE )
10687  {
10688  if( var->glbdom.lb > 0.5 )
10689  *infeasible = TRUE;
10690  else if( var->glbdom.ub > 0.5 )
10691  {
10692  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10693  * with the local bound, in this case we need to store the bound change as pending bound change
10694  */
10695  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10696  {
10697  assert(tree != NULL);
10698  assert(transprob != NULL);
10699  assert(SCIPprobIsTransformed(transprob));
10700 
10701  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10702  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10703  }
10704  else
10705  {
10706  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10707  }
10708 
10709  if( nbdchgs != NULL )
10710  (*nbdchgs)++;
10711  }
10712  }
10713  else
10714  {
10715  if( var->glbdom.ub < 0.5 )
10716  *infeasible = TRUE;
10717  else if( var->glbdom.lb < 0.5 )
10718  {
10719  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10720  * with the local bound, in this case we need to store the bound change as pending bound change
10721  */
10722  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10723  {
10724  assert(tree != NULL);
10725  assert(transprob != NULL);
10726  assert(SCIPprobIsTransformed(transprob));
10727 
10728  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10729  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10730  }
10731  else
10732  {
10733  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10734  }
10735 
10736  if( nbdchgs != NULL )
10737  (*nbdchgs)++;
10738  }
10739  }
10740 
10741  /* during presolving, the variable should have been removed immediately from all its cliques */
10742  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10743 
10744  return SCIP_OKAY;
10745 }
10746 
10747 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10748  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10749  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10750  * the opposite of the value they take in the clique
10751  */
10753  SCIP_VAR* var, /**< problem variable */
10754  BMS_BLKMEM* blkmem, /**< block memory */
10755  SCIP_SET* set, /**< global SCIP settings */
10756  SCIP_STAT* stat, /**< problem statistics */
10757  SCIP_PROB* transprob, /**< transformed problem */
10758  SCIP_PROB* origprob, /**< original problem */
10759  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10760  SCIP_REOPT* reopt, /**< reoptimization data structure */
10761  SCIP_LP* lp, /**< current LP data */
10762  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10763  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10764  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10765  SCIP_Bool value, /**< value of the variable in the clique */
10766  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10767  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10768  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10769  )
10770 {
10771  assert(var != NULL);
10772  assert(set != NULL);
10773  assert(var->scip == set->scip);
10774  assert(SCIPvarIsBinary(var));
10775  assert(infeasible != NULL);
10776 
10777  *infeasible = FALSE;
10778 
10779  /* get corresponding active problem variable */
10780  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10785  assert(SCIPvarIsBinary(var));
10786 
10787  /* only column and loose variables may be member of a clique */
10789  {
10790  SCIP_Bool doubleentry;
10791  SCIP_Bool oppositeentry;
10792 
10793  /* add variable to clique */
10794  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10795 
10796  /* add clique to variable's clique list */
10797  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10798 
10799  /* check consistency of cliquelist */
10800  SCIPcliquelistCheck(var->cliquelist, var);
10801 
10802  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10803  if( doubleentry )
10804  {
10805  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10806  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10807  }
10808 
10809  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10810  * to the opposite of the value they take in the clique
10811  */
10812  if( oppositeentry )
10813  {
10814  SCIP_VAR** vars;
10815  SCIP_Bool* values;
10816  int nvars;
10817  int i;
10818 
10819  nvars = SCIPcliqueGetNVars(clique);
10820  vars = SCIPcliqueGetVars(clique);
10821  values = SCIPcliqueGetValues(clique);
10822  for( i = 0; i < nvars && !(*infeasible); ++i )
10823  {
10824  if( vars[i] == var )
10825  continue;
10826 
10827  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10828  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10829  }
10830  }
10831  }
10832 
10833  return SCIP_OKAY;
10834 }
10835 
10836 /** adds a filled clique to the cliquelists of all corresponding variables */
10838  SCIP_VAR** vars, /**< problem variables */
10839  SCIP_Bool* values, /**< values of the variables in the clique */
10840  int nvars, /**< number of problem variables */
10841  BMS_BLKMEM* blkmem, /**< block memory */
10842  SCIP_SET* set, /**< global SCIP settings */
10843  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10844  )
10845 {
10846  SCIP_VAR* var;
10847  int v;
10848 
10849  assert(vars != NULL);
10850  assert(values != NULL);
10851  assert(nvars > 0);
10852  assert(set != NULL);
10853  assert(blkmem != NULL);
10854  assert(clique != NULL);
10855 
10856  for( v = nvars - 1; v >= 0; --v )
10857  {
10858  var = vars[v];
10859  assert(SCIPvarIsBinary(var));
10861 
10862  /* add clique to variable's clique list */
10863  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10864 
10865  /* check consistency of cliquelist */
10866  SCIPcliquelistCheck(var->cliquelist, var);
10867  }
10868 
10869  return SCIP_OKAY;
10870 }
10871 
10872 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10873  * itself
10874  */
10876  SCIP_VAR* var, /**< problem variable */
10877  BMS_BLKMEM* blkmem, /**< block memory */
10878  SCIP_SET* set, /**< global SCIP settings */
10879  SCIP_Bool value, /**< value of the variable in the clique */
10880  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10881  )
10882 {
10883  assert(var != NULL);
10884  assert(SCIPvarIsBinary(var));
10886 
10887  /* add clique to variable's clique list */
10888  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10889 
10890  return SCIP_OKAY;
10891 }
10892 
10893 
10894 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10895  * itself
10896  */
10898  SCIP_VAR* var, /**< problem variable */
10899  BMS_BLKMEM* blkmem, /**< block memory */
10900  SCIP_Bool value, /**< value of the variable in the clique */
10901  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10902  )
10903 {
10904  assert(var != NULL);
10905  assert(SCIPvarIsBinary(var));
10906 
10907  /* delete clique from variable's clique list */
10908  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10909 
10910  return SCIP_OKAY;
10911 }
10912 
10913 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10915  SCIP_VAR* var, /**< problem variable */
10916  BMS_BLKMEM* blkmem, /**< block memory */
10917  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10918  SCIP_Bool value, /**< value of the variable in the clique */
10919  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10920  )
10921 {
10922  assert(var != NULL);
10923  assert(SCIPvarIsBinary(var));
10924 
10925  /* get corresponding active problem variable */
10926  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10931  assert(SCIPvarIsBinary(var));
10932 
10933  /* only column and loose variables may be member of a clique */
10935  {
10936  /* delete clique from variable's clique list */
10937  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10938 
10939  /* delete variable from clique */
10940  SCIPcliqueDelVar(clique, cliquetable, var, value);
10941 
10942  /* check consistency of cliquelist */
10943  SCIPcliquelistCheck(var->cliquelist, var);
10944  }
10945 
10946  return SCIP_OKAY;
10947 }
10948 
10949 /** returns whether there is a clique that contains both given variable/value pairs;
10950  * the variables must be active binary variables;
10951  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10952  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10953  *
10954  * @note a variable with it's negated variable are NOT! in a clique
10955  * @note a variable with itself are in a clique
10956  */
10958  SCIP_VAR* var1, /**< first variable */
10959  SCIP_Bool value1, /**< value of first variable */
10960  SCIP_VAR* var2, /**< second variable */
10961  SCIP_Bool value2, /**< value of second variable */
10962  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10963  )
10964 {
10965  assert(var1 != NULL);
10966  assert(var2 != NULL);
10967  assert(SCIPvarIsActive(var1));
10968  assert(SCIPvarIsActive(var2));
10969  assert(SCIPvarIsBinary(var1));
10970  assert(SCIPvarIsBinary(var2));
10971 
10972  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10973  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10974 }
10975 
10976 /** actually changes the branch factor of the variable and of all parent variables */
10977 static
10979  SCIP_VAR* var, /**< problem variable */
10980  SCIP_SET* set, /**< global SCIP settings */
10981  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10982  )
10983 {
10984  SCIP_VAR* parentvar;
10985  SCIP_Real eps;
10986  int i;
10987 
10988  assert(var != NULL);
10989  assert(set != NULL);
10990  assert(var->scip == set->scip);
10991 
10992  /* only use positive values */
10993  eps = SCIPsetEpsilon(set);
10994  branchfactor = MAX(branchfactor, eps);
10995 
10996  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10997 
10998  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10999  return SCIP_OKAY;
11000 
11001  /* change the branch factor */
11002  var->branchfactor = branchfactor;
11003 
11004  /* process parent variables */
11005  for( i = 0; i < var->nparentvars; ++i )
11006  {
11007  parentvar = var->parentvars[i];
11008  assert(parentvar != NULL);
11009 
11010  switch( SCIPvarGetStatus(parentvar) )
11011  {
11013  /* do not change priorities across the border between transformed and original problem */
11014  break;
11015 
11016  case SCIP_VARSTATUS_COLUMN:
11017  case SCIP_VARSTATUS_LOOSE:
11018  case SCIP_VARSTATUS_FIXED:
11020  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11021  SCIPABORT();
11022  return SCIP_INVALIDDATA; /*lint !e527*/
11023 
11026  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11027  break;
11028 
11029  default:
11030  SCIPerrorMessage("unknown variable status\n");
11031  SCIPABORT();
11032  return SCIP_ERROR; /*lint !e527*/
11033  }
11034  }
11035 
11036  return SCIP_OKAY;
11037 }
11038 
11039 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11040  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11041  */
11043  SCIP_VAR* var, /**< problem variable */
11044  SCIP_SET* set, /**< global SCIP settings */
11045  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11046  )
11047 {
11048  int v;
11049 
11050  assert(var != NULL);
11051  assert(set != NULL);
11052  assert(var->scip == set->scip);
11053  assert(branchfactor >= 0.0);
11054 
11055  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11056 
11057  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11058  return SCIP_OKAY;
11059 
11060  /* change priorities of attached variables */
11061  switch( SCIPvarGetStatus(var) )
11062  {
11064  if( var->data.original.transvar != NULL )
11065  {
11066  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11067  }
11068  else
11069  {
11070  assert(set->stage == SCIP_STAGE_PROBLEM);
11071  var->branchfactor = branchfactor;
11072  }
11073  break;
11074 
11075  case SCIP_VARSTATUS_COLUMN:
11076  case SCIP_VARSTATUS_LOOSE:
11077  case SCIP_VARSTATUS_FIXED:
11078  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11079  break;
11080 
11082  assert(var->data.aggregate.var != NULL);
11083  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11084  break;
11085 
11087  assert(!var->donotmultaggr);
11088  for( v = 0; v < var->data.multaggr.nvars; ++v )
11089  {
11090  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11091  }
11092  break;
11093 
11095  assert(var->negatedvar != NULL);
11097  assert(var->negatedvar->negatedvar == var);
11098  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11099  break;
11100 
11101  default:
11102  SCIPerrorMessage("unknown variable status\n");
11103  SCIPABORT();
11104  return SCIP_ERROR; /*lint !e527*/
11105  }
11106 
11107  return SCIP_OKAY;
11108 }
11109 
11110 /** actually changes the branch priority of the variable and of all parent variables */
11111 static
11113  SCIP_VAR* var, /**< problem variable */
11114  int branchpriority /**< branching priority of the variable */
11115  )
11116 {
11117  SCIP_VAR* parentvar;
11118  int i;
11119 
11120  assert(var != NULL);
11121 
11122  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11123  var->name, var->branchpriority, branchpriority);
11124 
11125  if( branchpriority == var->branchpriority )
11126  return SCIP_OKAY;
11127 
11128  /* change the branch priority */
11129  var->branchpriority = branchpriority;
11130 
11131  /* process parent variables */
11132  for( i = 0; i < var->nparentvars; ++i )
11133  {
11134  parentvar = var->parentvars[i];
11135  assert(parentvar != NULL);
11136 
11137  switch( SCIPvarGetStatus(parentvar) )
11138  {
11140  /* do not change priorities across the border between transformed and original problem */
11141  break;
11142 
11143  case SCIP_VARSTATUS_COLUMN:
11144  case SCIP_VARSTATUS_LOOSE:
11145  case SCIP_VARSTATUS_FIXED:
11147  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11148  SCIPABORT();
11149  return SCIP_INVALIDDATA; /*lint !e527*/
11150 
11153  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11154  break;
11155 
11156  default:
11157  SCIPerrorMessage("unknown variable status\n");
11158  return SCIP_ERROR;
11159  }
11160  }
11161 
11162  return SCIP_OKAY;
11163 }
11164 
11165 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11166  * with lower priority in selection of branching variable
11167  */
11169  SCIP_VAR* var, /**< problem variable */
11170  int branchpriority /**< branching priority of the variable */
11171  )
11172 {
11173  int v;
11174 
11175  assert(var != NULL);
11176 
11177  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11178 
11179  if( var->branchpriority == branchpriority )
11180  return SCIP_OKAY;
11181 
11182  /* change priorities of attached variables */
11183  switch( SCIPvarGetStatus(var) )
11184  {
11186  if( var->data.original.transvar != NULL )
11187  {
11188  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11189  }
11190  else
11191  var->branchpriority = branchpriority;
11192  break;
11193 
11194  case SCIP_VARSTATUS_COLUMN:
11195  case SCIP_VARSTATUS_LOOSE:
11196  case SCIP_VARSTATUS_FIXED:
11197  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11198  break;
11199 
11201  assert(var->data.aggregate.var != NULL);
11202  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11203  break;
11204 
11206  assert(!var->donotmultaggr);
11207  for( v = 0; v < var->data.multaggr.nvars; ++v )
11208  {
11209  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11210  }
11211  break;
11212 
11214  assert(var->negatedvar != NULL);
11216  assert(var->negatedvar->negatedvar == var);
11217  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11218  break;
11219 
11220  default:
11221  SCIPerrorMessage("unknown variable status\n");
11222  SCIPABORT();
11223  return SCIP_ERROR; /*lint !e527*/
11224  }
11225 
11226  return SCIP_OKAY;
11227 }
11228 
11229 /** actually changes the branch direction of the variable and of all parent variables */
11230 static
11232  SCIP_VAR* var, /**< problem variable */
11233  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11234  )
11235 {
11236  SCIP_VAR* parentvar;
11237  int i;
11238 
11239  assert(var != NULL);
11240 
11241  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11242  var->name, var->branchdirection, branchdirection);
11243 
11244  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11245  return SCIP_OKAY;
11246 
11247  /* change the branch direction */
11248  var->branchdirection = branchdirection; /*lint !e641*/
11249 
11250  /* process parent variables */
11251  for( i = 0; i < var->nparentvars; ++i )
11252  {
11253  parentvar = var->parentvars[i];
11254  assert(parentvar != NULL);
11255 
11256  switch( SCIPvarGetStatus(parentvar) )
11257  {
11259  /* do not change directions across the border between transformed and original problem */
11260  break;
11261 
11262  case SCIP_VARSTATUS_COLUMN:
11263  case SCIP_VARSTATUS_LOOSE:
11264  case SCIP_VARSTATUS_FIXED:
11266  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11267  SCIPABORT();
11268  return SCIP_INVALIDDATA; /*lint !e527*/
11269 
11271  if( parentvar->data.aggregate.scalar > 0.0 )
11272  {
11273  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11274  }
11275  else
11276  {
11277  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11278  }
11279  break;
11280 
11282  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11283  break;
11284 
11285  default:
11286  SCIPerrorMessage("unknown variable status\n");
11287  SCIPABORT();
11288  return SCIP_ERROR; /*lint !e527*/
11289  }
11290  }
11291 
11292  return SCIP_OKAY;
11293 }
11294 
11295 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11296  * with lower direction in selection of branching variable
11297  */
11299  SCIP_VAR* var, /**< problem variable */
11300  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11301  )
11302 {
11303  int v;
11304 
11305  assert(var != NULL);
11306 
11307  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11308 
11309  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11310  return SCIP_OKAY;
11311 
11312  /* change directions of attached variables */
11313  switch( SCIPvarGetStatus(var) )
11314  {
11316  if( var->data.original.transvar != NULL )
11317  {
11318  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11319  }
11320  else
11321  var->branchdirection = branchdirection; /*lint !e641*/
11322  break;
11323 
11324  case SCIP_VARSTATUS_COLUMN:
11325  case SCIP_VARSTATUS_LOOSE:
11326  case SCIP_VARSTATUS_FIXED:
11327  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11328  break;
11329 
11331  assert(var->data.aggregate.var != NULL);
11332  if( var->data.aggregate.scalar > 0.0 )
11333  {
11334  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11335  }
11336  else
11337  {
11339  }
11340  break;
11341 
11343  assert(!var->donotmultaggr);
11344  for( v = 0; v < var->data.multaggr.nvars; ++v )
11345  {
11346  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11347  assert(var->data.multaggr.vars[v] != NULL);
11349  {
11350  if( var->data.multaggr.scalars[v] > 0.0 )
11351  {
11352  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11353  }
11354  else
11355  {
11357  }
11358  }
11359  }
11360  break;
11361 
11363  assert(var->negatedvar != NULL);
11365  assert(var->negatedvar->negatedvar == var);
11367  break;
11368 
11369  default:
11370  SCIPerrorMessage("unknown variable status\n");
11371  SCIPABORT();
11372  return SCIP_ERROR; /*lint !e527*/
11373  }
11374 
11375  return SCIP_OKAY;
11376 }
11377 
11378 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11379  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11380  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11381  * are equal, which means both variables are equal
11382  */
11384  SCIP_VAR* var1, /**< first problem variable */
11385  SCIP_VAR* var2 /**< second problem variable */
11386  )
11387 {
11388  assert(var1 != NULL);
11389  assert(var2 != NULL);
11392 
11394  var1 = SCIPvarGetNegatedVar(var1);
11396  var2 = SCIPvarGetNegatedVar(var2);
11397 
11398  assert(var1 != NULL);
11399  assert(var2 != NULL);
11400 
11401  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11402  return -1;
11403  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11404  return +1;
11405 
11406  assert(var1 == var2);
11407  return 0;
11408 }
11409 
11410 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11411  * variables are handled as the same variables
11412  */
11413 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11415  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11416 }
11417 
11418 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11419  * variable index; returns 0 if both indices are equal, which means both variables are equal
11420  */
11421 int SCIPvarCompare(
11422  SCIP_VAR* var1, /**< first problem variable */
11423  SCIP_VAR* var2 /**< second problem variable */
11424  )
11425 {
11426  assert(var1 != NULL);
11427  assert(var2 != NULL);
11428 
11429  if( var1->index < var2->index )
11430  return -1;
11431  else if( var1->index > var2->index )
11432  return +1;
11433  else
11434  {
11435  assert(var1 == var2);
11436  return 0;
11437  }
11438 }
11439 
11440 /** comparison method for sorting variables by non-decreasing index */
11441 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11443  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11444 }
11445 
11446 /** comparison method for sorting variables by non-decreasing objective coefficient */
11447 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11449  SCIP_Real obj1;
11450  SCIP_Real obj2;
11451 
11452  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11453  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11454 
11455  if( obj1 < obj2 )
11456  return -1;
11457  else if( obj1 > obj2 )
11458  return +1;
11459  else
11460  return 0;
11461 }
11462 
11463 /** hash key retrieval function for variables */
11464 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11465 { /*lint --e{715}*/
11466  return elem;
11467 }
11468 
11469 /** returns TRUE iff the indices of both variables are equal */
11470 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11471 { /*lint --e{715}*/
11472  if( key1 == key2 )
11473  return TRUE;
11474  return FALSE;
11475 }
11476 
11477 /** returns the hash value of the key */
11478 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11479 { /*lint --e{715}*/
11480  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11481  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11482 }
11483 
11484 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11486  SCIP_SET* set, /**< global SCIP settings */
11487  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11488  * variables, if enough slots exist
11489  */
11490  int* nvars, /**< number of given variables, and as output number of active variables,
11491  * if enough slots exist
11492  */
11493  int varssize, /**< available slots in vars array */
11494  int* requiredsize /**< pointer to store the required array size for the active variables */
11495  )
11496 {
11497  SCIP_VAR** activevars;
11498  int nactivevars;
11499  int activevarssize;
11500 
11501  SCIP_VAR* var;
11502  int v;
11503 
11504  SCIP_VAR** tmpvars;
11505  SCIP_VAR** multvars;
11506  int tmpvarssize;
11507  int ntmpvars;
11508  int noldtmpvars;
11509  int nmultvars;
11510 
11511  assert(set != NULL);
11512  assert(nvars != NULL);
11513  assert(vars != NULL || *nvars == 0);
11514  assert(varssize >= *nvars);
11515  assert(requiredsize != NULL);
11516 
11517  *requiredsize = 0;
11518 
11519  if( *nvars == 0 )
11520  return SCIP_OKAY;
11521 
11522  nactivevars = 0;
11523  activevarssize = *nvars;
11524  ntmpvars = *nvars;
11525  tmpvarssize = *nvars;
11526 
11527  /* temporary memory */
11528  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11529  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11530 
11531  noldtmpvars = ntmpvars;
11532 
11533  /* sort all variables to combine equal variables easily */
11534  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11535  for( v = ntmpvars - 1; v > 0; --v )
11536  {
11537  /* combine same variables */
11538  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11539  {
11540  --ntmpvars;
11541  tmpvars[v] = tmpvars[ntmpvars];
11542  }
11543  }
11544  /* sort all variables again to combine equal variables later on */
11545  if( noldtmpvars > ntmpvars )
11546  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11547 
11548  /* collect for each variable the representation in active variables */
11549  while( ntmpvars >= 1 )
11550  {
11551  --ntmpvars;
11552  var = tmpvars[ntmpvars];
11553  assert( var != NULL );
11554 
11555  switch( SCIPvarGetStatus(var) )
11556  {
11558  if( var->data.original.transvar == NULL )
11559  {
11560  SCIPerrorMessage("original variable has no transformed variable attached\n");
11561  SCIPABORT();
11562  return SCIP_INVALIDDATA; /*lint !e527*/
11563  }
11564  tmpvars[ntmpvars] = var->data.original.transvar;
11565  ++ntmpvars;
11566  break;
11567 
11569  tmpvars[ntmpvars] = var->data.aggregate.var;
11570  ++ntmpvars;
11571  break;
11572 
11574  tmpvars[ntmpvars] = var->negatedvar;
11575  ++ntmpvars;
11576  break;
11577 
11578  case SCIP_VARSTATUS_LOOSE:
11579  case SCIP_VARSTATUS_COLUMN:
11580  /* check for space in temporary memory */
11581  if( nactivevars >= activevarssize )
11582  {
11583  activevarssize *= 2;
11584  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11585  assert(nactivevars < activevarssize);
11586  }
11587  activevars[nactivevars] = var;
11588  nactivevars++;
11589  break;
11590 
11592  /* x = a_1*y_1 + ... + a_n*y_n + c */
11593  nmultvars = var->data.multaggr.nvars;
11594  multvars = var->data.multaggr.vars;
11595 
11596  /* check for space in temporary memory */
11597  if( nmultvars + ntmpvars > tmpvarssize )
11598  {
11599  while( nmultvars + ntmpvars > tmpvarssize )
11600  tmpvarssize *= 2;
11601  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11602  assert(nmultvars + ntmpvars <= tmpvarssize);
11603  }
11604 
11605  /* copy all multi-aggregation variables into our working array */
11606  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11607 
11608  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11609  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11610 
11611  ntmpvars += nmultvars;
11612  noldtmpvars = ntmpvars;
11613 
11614  /* sort all variables to combine equal variables easily */
11615  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11616  for( v = ntmpvars - 1; v > 0; --v )
11617  {
11618  /* combine same variables */
11619  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11620  {
11621  --ntmpvars;
11622  tmpvars[v] = tmpvars[ntmpvars];
11623  }
11624  }
11625  /* sort all variables again to combine equal variables later on */
11626  if( noldtmpvars > ntmpvars )
11627  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11628 
11629  break;
11630 
11631  case SCIP_VARSTATUS_FIXED:
11632  /* no need for memorizing fixed variables */
11633  break;
11634 
11635  default:
11636  SCIPerrorMessage("unknown variable status\n");
11637  SCIPABORT();
11638  return SCIP_INVALIDDATA; /*lint !e527*/
11639  }
11640  }
11641 
11642  /* sort variable array by variable index */
11643  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11644 
11645  /* eliminate duplicates and count required size */
11646  v = nactivevars - 1;
11647  while( v > 0 )
11648  {
11649  /* combine both variable since they are the same */
11650  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11651  {
11652  --nactivevars;
11653  activevars[v] = activevars[nactivevars];
11654  }
11655  --v;
11656  }
11657  *requiredsize = nactivevars;
11658 
11659  if( varssize >= *requiredsize )
11660  {
11661  assert(vars != NULL);
11662 
11663  *nvars = *requiredsize;
11664  BMScopyMemoryArray(vars, activevars, nactivevars);
11665  }
11666 
11667  SCIPsetFreeBufferArray(set, &tmpvars);
11668  SCIPsetFreeBufferArray(set, &activevars);
11669 
11670  return SCIP_OKAY;
11671 }
11672 
11673 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11674  * @note the content of the given array will/might change
11675  */
11676 void SCIPvarsGetProbvar(
11677  SCIP_VAR** vars, /**< array of problem variables */
11678  int nvars /**< number of variables */
11679  )
11680 {
11681  int v;
11682 
11683  assert(vars != NULL || nvars == 0);
11684 
11685  for( v = nvars - 1; v >= 0; --v )
11686  {
11687  assert(vars != NULL);
11688  assert(vars[v] != NULL);
11689 
11690  vars[v] = SCIPvarGetProbvar(vars[v]);
11691  assert(vars[v] != NULL);
11692  }
11693 }
11694 
11695 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11697  SCIP_VAR* var /**< problem variable */
11698  )
11699 {
11700  SCIP_VAR* retvar;
11701 
11702  assert(var != NULL);
11703 
11704  retvar = var;
11705 
11706  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11707 
11708  while( TRUE ) /*lint !e716 */
11709  {
11710  assert(retvar != NULL);
11711 
11712  switch( SCIPvarGetStatus(retvar) )
11713  {
11715  if( retvar->data.original.transvar == NULL )
11716  {
11717  SCIPerrorMessage("original variable has no transformed variable attached\n");
11718  SCIPABORT();
11719  return NULL; /*lint !e527 */
11720  }
11721  retvar = retvar->data.original.transvar;
11722  break;
11723 
11724  case SCIP_VARSTATUS_LOOSE:
11725  case SCIP_VARSTATUS_COLUMN:
11726  case SCIP_VARSTATUS_FIXED:
11727  return retvar;
11728 
11730  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11731  if ( retvar->data.multaggr.nvars == 1 )
11732  retvar = retvar->data.multaggr.vars[0];
11733  else
11734  return retvar;
11735  break;
11736 
11738  retvar = retvar->data.aggregate.var;
11739  break;
11740 
11742  retvar = retvar->negatedvar;
11743  break;
11744 
11745  default:
11746  SCIPerrorMessage("unknown variable status\n");
11747  SCIPABORT();
11748  return NULL; /*lint !e527*/
11749  }
11750  }
11751 }
11752 
11753 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11754  * negation status of each variable
11755  */
11757  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11758  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11759  int nvars /**< number of variables and values in vars and negated array */
11760  )
11761 {
11762  SCIP_VAR** var;
11763  SCIP_Bool* negated;
11764  int v;
11765 
11766  assert(vars != NULL);
11767  assert(*vars != NULL || nvars == 0);
11768  assert(negatedarr != NULL);
11769  assert(*negatedarr != NULL || nvars == 0);
11770 
11771  for( v = nvars - 1; v >= 0; --v )
11772  {
11773  var = &((*vars)[v]);
11774  negated = &((*negatedarr)[v]);
11775 
11776  /* get problem variable */
11777  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11778  }
11779 
11780  return SCIP_OKAY;
11781 }
11782 
11783 
11784 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11785  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11786  * FALSE is used)
11787  */
11789  SCIP_VAR** var, /**< pointer to binary problem variable */
11790  SCIP_Bool* negated /**< pointer to update the negation status */
11791  )
11792 {
11794 #ifndef NDEBUG
11795  SCIP_Real constant = 0.0;
11796  SCIP_Bool orignegated;
11797 #endif
11798 
11799  assert(var != NULL);
11800  assert(*var != NULL);
11801  assert(negated != NULL);
11802  assert(SCIPvarIsBinary(*var));
11803 
11804 #ifndef NDEBUG
11805  orignegated = *negated;
11806 #endif
11807 
11808  while( !active && *var != NULL )
11809  {
11810  switch( SCIPvarGetStatus(*var) )
11811  {
11813  if( (*var)->data.original.transvar == NULL )
11814  return SCIP_OKAY;
11815  *var = (*var)->data.original.transvar;
11816  break;
11817 
11818  case SCIP_VARSTATUS_LOOSE:
11819  case SCIP_VARSTATUS_COLUMN:
11820  case SCIP_VARSTATUS_FIXED:
11821  active = TRUE;
11822  break;
11823 
11825  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11826  if ( (*var)->data.multaggr.nvars == 1 )
11827  {
11828  assert( (*var)->data.multaggr.vars != NULL );
11829  assert( (*var)->data.multaggr.scalars != NULL );
11830  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11831  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11832 
11833  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11834  * another variable which needs to be fixed
11835  *
11836  * e.g. x = y - 1 => (x = 0 && y = 1)
11837  * e.g. x = y + 1 => (x = 1 && y = 0)
11838  *
11839  * is this special case we need to return the muti-aggregation
11840  */
11841  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)) )
11842  {
11843  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11844  }
11845  else
11846  {
11847  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11848  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11849  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11850  * we will return the aggregated variable;
11851  */
11852  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11853  {
11854  active = TRUE;
11855  break;
11856  }
11857 
11858  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11859  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11860  * so if this is the case, we will return the aggregated variable
11861  */
11862  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11863  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11864  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11865 
11866  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11867  {
11868  active = TRUE;
11869  break;
11870  }
11871 
11872  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11873 
11874  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11875  {
11876  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11877  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11878  * variable itself is multi-aggregated again?
11879  */
11880  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11881  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11882  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
11883  }
11884  else
11885  {
11886  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11887 #ifndef NDEBUG
11888  constant += (*negated) != orignegated ? -1.0 : 1.0;
11889 #endif
11890 
11891  *negated = !(*negated);
11892  }
11893  *var = (*var)->data.multaggr.vars[0];
11894  break;
11895  }
11896  }
11897  active = TRUE;
11898  break;
11899 
11900  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11901  assert((*var)->data.aggregate.var != NULL);
11902  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11903  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11904 #ifndef NDEBUG
11905  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11906 #endif
11907 
11908  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11909  *var = (*var)->data.aggregate.var;
11910  break;
11911 
11912  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11913  assert((*var)->negatedvar != NULL);
11914 #ifndef NDEBUG
11915  constant += (*negated) != orignegated ? -1.0 : 1.0;
11916 #endif
11917 
11918  *negated = !(*negated);
11919  *var = (*var)->negatedvar;
11920  break;
11921 
11922  default:
11923  SCIPerrorMessage("unknown variable status\n");
11924  return SCIP_INVALIDDATA;
11925  }
11926  }
11927  assert(active == (*var != NULL));
11928 
11929  if( active )
11930  {
11931  assert(SCIPvarIsBinary(*var));
11932  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11933  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11934 
11935  return SCIP_OKAY;
11936  }
11937  else
11938  {
11939  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11940  return SCIP_INVALIDDATA;
11941  }
11942 }
11943 
11944 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11945  * values
11946  */
11948  SCIP_VAR** var, /**< pointer to problem variable */
11949  SCIP_Real* bound, /**< pointer to bound value to transform */
11950  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11951  )
11952 {
11953  assert(var != NULL);
11954  assert(*var != NULL);
11955  assert(bound != NULL);
11956  assert(boundtype != NULL);
11957 
11958  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11959 
11960  switch( SCIPvarGetStatus(*var) )
11961  {
11963  if( (*var)->data.original.transvar == NULL )
11964  {
11965  SCIPerrorMessage("original variable has no transformed variable attached\n");
11966  return SCIP_INVALIDDATA;
11967  }
11968  *var = (*var)->data.original.transvar;
11969  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11970  break;
11971 
11972  case SCIP_VARSTATUS_LOOSE:
11973  case SCIP_VARSTATUS_COLUMN:
11974  case SCIP_VARSTATUS_FIXED:
11975  break;
11976 
11978  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11979  if ( (*var)->data.multaggr.nvars == 1 )
11980  {
11981  assert( (*var)->data.multaggr.vars != NULL );
11982  assert( (*var)->data.multaggr.scalars != NULL );
11983  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11984 
11985  (*bound) /= (*var)->data.multaggr.scalars[0];
11986  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11987  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11988  {
11989  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11990  *boundtype = SCIP_BOUNDTYPE_UPPER;
11991  else
11992  *boundtype = SCIP_BOUNDTYPE_LOWER;
11993  }
11994  *var = (*var)->data.multaggr.vars[0];
11995  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11996  }
11997  break;
11998 
11999  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12000  assert((*var)->data.aggregate.var != NULL);
12001  assert((*var)->data.aggregate.scalar != 0.0);
12002 
12003  (*bound) /= (*var)->data.aggregate.scalar;
12004  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12005  if( (*var)->data.aggregate.scalar < 0.0 )
12006  {
12007  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12008  *boundtype = SCIP_BOUNDTYPE_UPPER;
12009  else
12010  *boundtype = SCIP_BOUNDTYPE_LOWER;
12011  }
12012  *var = (*var)->data.aggregate.var;
12013  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12014  break;
12015 
12016  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12017  assert((*var)->negatedvar != NULL);
12018  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12019  assert((*var)->negatedvar->negatedvar == *var);
12020  (*bound) = (*var)->data.negate.constant - *bound;
12021  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12022  *boundtype = SCIP_BOUNDTYPE_UPPER;
12023  else
12024  *boundtype = SCIP_BOUNDTYPE_LOWER;
12025  *var = (*var)->negatedvar;
12026  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12027  break;
12028 
12029  default:
12030  SCIPerrorMessage("unknown variable status\n");
12031  return SCIP_INVALIDDATA;
12032  }
12033 
12034  return SCIP_OKAY;
12035 }
12036 
12037 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12038  * values
12039  */
12041  SCIP_VAR** var, /**< pointer to problem variable */
12042  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12043  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12044  )
12045 {
12046  assert(var != NULL);
12047  assert(*var != NULL);
12048  assert(left != NULL);
12049  assert(right != NULL);
12050 
12051  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12052 
12053  switch( SCIPvarGetStatus(*var) )
12054  {
12056  if( (*var)->data.original.transvar == NULL )
12057  {
12058  SCIPerrorMessage("original variable has no transformed variable attached\n");
12059  return SCIP_INVALIDDATA;
12060  }
12061  *var = (*var)->data.original.transvar;
12062  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12063  break;
12064 
12065  case SCIP_VARSTATUS_LOOSE:
12066  case SCIP_VARSTATUS_COLUMN:
12067  case SCIP_VARSTATUS_FIXED:
12069  break;
12070 
12071  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12072  assert((*var)->data.aggregate.var != NULL);
12073  assert((*var)->data.aggregate.scalar != 0.0);
12074 
12075  /* scale back */
12076  (*left) /= (*var)->data.aggregate.scalar;
12077  (*right) /= (*var)->data.aggregate.scalar;
12078 
12079  /* shift back */
12080  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12081  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12082 
12083  *var = (*var)->data.aggregate.var;
12084 
12085  /* check if the interval bounds have to swapped */
12086  if( (*var)->data.aggregate.scalar < 0.0 )
12087  {
12088  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12089  }
12090  else
12091  {
12092  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12093  }
12094  break;
12095 
12096  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12097  assert((*var)->negatedvar != NULL);
12098  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12099  assert((*var)->negatedvar->negatedvar == *var);
12100 
12101  /* shift and scale back */
12102  (*left) = (*var)->data.negate.constant - (*left);
12103  (*right) = (*var)->data.negate.constant - (*right);
12104 
12105  *var = (*var)->negatedvar;
12106 
12107  /* through the negated variable the left and right interval bound have to swapped */
12108  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12109  break;
12110 
12111  default:
12112  SCIPerrorMessage("unknown variable status\n");
12113  return SCIP_INVALIDDATA;
12114  }
12115 
12116  return SCIP_OKAY;
12117 }
12118 
12119 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12120  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12121  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12122  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12123  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12124  */
12126  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12127  SCIP_SET* set, /**< global SCIP settings */
12128  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12129  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12130  )
12131 {
12132  assert(var != NULL);
12133  assert(scalar != NULL);
12134  assert(constant != NULL);
12135 
12136  while( *var != NULL )
12137  {
12138  switch( SCIPvarGetStatus(*var) )
12139  {
12141  if( (*var)->data.original.transvar == NULL )
12142  {
12143  SCIPerrorMessage("original variable has no transformed variable attached\n");
12144  return SCIP_INVALIDDATA;
12145  }
12146  *var = (*var)->data.original.transvar;
12147  break;
12148 
12149  case SCIP_VARSTATUS_LOOSE:
12150  case SCIP_VARSTATUS_COLUMN:
12151  return SCIP_OKAY;
12152 
12153  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12154  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12155  {
12156  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12157  {
12158  assert(*scalar != 0.0);
12159  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12160  (*constant) = SCIPsetInfinity(set);
12161  else
12162  (*constant) = -SCIPsetInfinity(set);
12163  }
12164  else
12165  (*constant) += *scalar * (*var)->glbdom.lb;
12166  }
12167 #ifndef NDEBUG
12168  else
12169  {
12170  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12171  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12172  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12173  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12174  }
12175 #endif
12176  *scalar = 0.0;
12177  return SCIP_OKAY;
12178 
12180  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12181  if ( (*var)->data.multaggr.nvars == 1 )
12182  {
12183  assert((*var)->data.multaggr.vars != NULL);
12184  assert((*var)->data.multaggr.scalars != NULL);
12185  assert((*var)->data.multaggr.vars[0] != NULL);
12186  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12187  {
12188  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12189  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12190  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12191  */
12192  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12193  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12194  {
12195  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12196  {
12197  assert(!SCIPsetIsInfinity(set, -(*constant)));
12198  (*constant) = SCIPsetInfinity(set);
12199  }
12200  else
12201  {
12202  assert(!SCIPsetIsInfinity(set, *constant));
12203  (*constant) = -SCIPsetInfinity(set);
12204  }
12205  (*scalar) = 0.0;
12206  }
12207  else
12208  (*constant) += *scalar * (*var)->data.multaggr.constant;
12209  }
12210  (*scalar) *= (*var)->data.multaggr.scalars[0];
12211  *var = (*var)->data.multaggr.vars[0];
12212  break;
12213  }
12214  return SCIP_OKAY;
12215 
12216  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12217  assert((*var)->data.aggregate.var != NULL);
12218  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12219  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12220  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12221  (*constant) += *scalar * (*var)->data.aggregate.constant;
12222  (*scalar) *= (*var)->data.aggregate.scalar;
12223  *var = (*var)->data.aggregate.var;
12224  break;
12225 
12226  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12227  assert((*var)->negatedvar != NULL);
12228  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12229  assert((*var)->negatedvar->negatedvar == *var);
12230  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12231  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12232  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12233  (*constant) += *scalar * (*var)->data.negate.constant;
12234  (*scalar) *= -1.0;
12235  *var = (*var)->negatedvar;
12236  break;
12237 
12238  default:
12239  SCIPerrorMessage("unknown variable status\n");
12240  SCIPABORT();
12241  return SCIP_INVALIDDATA; /*lint !e527*/
12242  }
12243  }
12244  *scalar = 0.0;
12245 
12246  return SCIP_OKAY;
12247 }
12248 
12249 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12250  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12251  */
12253  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12254  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12255  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12256  )
12257 {
12258  SCIP_VAR* parentvar;
12259 
12260  assert(var != NULL);
12261  assert(*var != NULL);
12262  assert(scalar != NULL);
12263  assert(constant != NULL);
12264 
12265  while( !SCIPvarIsOriginal(*var) )
12266  {
12267  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12268  * var
12269  */
12270  if( (*var)->nparentvars == 0 )
12271  {
12272  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12273  * space
12274  */
12276  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12277  {
12278  *scalar *= -1.0;
12279  *constant -= (*var)->data.negate.constant * (*scalar);
12280  *var = (*var)->negatedvar;
12281 
12282  continue;
12283  }
12284  /* if the variables does not have any parent the variables was created during solving and has no original
12285  * counterpart
12286  */
12287  else
12288  {
12289  *var = NULL;
12290 
12291  return SCIP_OKAY;
12292  }
12293  }
12294 
12295  /* follow the link to the first parent variable */
12296  parentvar = (*var)->parentvars[0];
12297  assert(parentvar != NULL);
12298 
12299  switch( SCIPvarGetStatus(parentvar) )
12300  {
12302  break;
12303 
12304  case SCIP_VARSTATUS_COLUMN:
12305  case SCIP_VARSTATUS_LOOSE:
12306  case SCIP_VARSTATUS_FIXED:
12308  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12309  return SCIP_INVALIDDATA;
12310 
12311  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12312  assert(parentvar->data.aggregate.var == *var);
12313  assert(parentvar->data.aggregate.scalar != 0.0);
12314  *scalar /= parentvar->data.aggregate.scalar;
12315  *constant -= parentvar->data.aggregate.constant * (*scalar);
12316  break;
12317 
12318  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12319  assert(parentvar->negatedvar != NULL);
12320  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12321  assert(parentvar->negatedvar->negatedvar == parentvar);
12322  *scalar *= -1.0;
12323  *constant -= parentvar->data.negate.constant * (*scalar);
12324  break;
12325 
12326  default:
12327  SCIPerrorMessage("unknown variable status\n");
12328  return SCIP_INVALIDDATA;
12329  }
12330 
12331  assert( parentvar != NULL );
12332  *var = parentvar;
12333  }
12334 
12335  return SCIP_OKAY;
12336 }
12337 
12338 /** returns whether the given variable is the direct counterpart of an original problem variable */
12340  SCIP_VAR* var /**< problem variable */
12341  )
12342 {
12343  SCIP_VAR* parentvar;
12344  assert(var != NULL);
12345 
12346  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12347  return FALSE;
12348 
12349  assert(var->parentvars != NULL);
12350  parentvar = var->parentvars[0];
12351  assert(parentvar != NULL);
12352 
12353  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12354  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12355  parentvar = parentvar->parentvars[0];
12356  assert( parentvar != NULL );
12357 
12358  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12359 }
12360 
12361 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12362  * the variable's own data due to diving, that operate only on the LP without updating the variables
12363  */
12365  SCIP_VAR* var /**< problem variable */
12366  )
12367 {
12368  assert(var != NULL);
12369 
12370  /* get bounds of attached variables */
12371  switch( SCIPvarGetStatus(var) )
12372  {
12374  assert(var->data.original.transvar != NULL);
12375  return SCIPvarGetObjLP(var->data.original.transvar);
12376 
12377  case SCIP_VARSTATUS_COLUMN:
12378  assert(var->data.col != NULL);
12379  return SCIPcolGetObj(var->data.col);
12380 
12381  case SCIP_VARSTATUS_LOOSE:
12382  case SCIP_VARSTATUS_FIXED:
12383  return var->obj;
12384 
12385  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12386  assert(var->data.aggregate.var != NULL);
12387  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12388 
12390  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12391  SCIPABORT();
12392  return 0.0; /*lint !e527*/
12393 
12394  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12395  assert(var->negatedvar != NULL);
12397  assert(var->negatedvar->negatedvar == var);
12398  return -SCIPvarGetObjLP(var->negatedvar);
12399 
12400  default:
12401  SCIPerrorMessage("unknown variable status\n");
12402  SCIPABORT();
12403  return 0.0; /*lint !e527*/
12404  }
12405 }
12406 
12407 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12408  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12409  */
12411  SCIP_VAR* var, /**< problem variable */
12412  SCIP_SET* set /**< global SCIP settings */
12413  )
12414 {
12415  assert(var != NULL);
12416  assert(set != NULL);
12417  assert(var->scip == set->scip);
12418 
12419  /* get bounds of attached variables */
12420  switch( SCIPvarGetStatus(var) )
12421  {
12423  assert(var->data.original.transvar != NULL);
12424  return SCIPvarGetLbLP(var->data.original.transvar, set);
12425 
12426  case SCIP_VARSTATUS_COLUMN:
12427  assert(var->data.col != NULL);
12428  return SCIPcolGetLb(var->data.col);
12429 
12430  case SCIP_VARSTATUS_LOOSE:
12431  case SCIP_VARSTATUS_FIXED:
12432  return var->locdom.lb;
12433 
12434  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12435  assert(var->data.aggregate.var != NULL);
12436  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12437  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12438  {
12439  return -SCIPsetInfinity(set);
12440  }
12441  else if( var->data.aggregate.scalar > 0.0 )
12442  {
12443  /* a > 0 -> get lower bound of y */
12444  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12445  }
12446  else if( var->data.aggregate.scalar < 0.0 )
12447  {
12448  /* a < 0 -> get upper bound of y */
12449  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12450  }
12451  else
12452  {
12453  SCIPerrorMessage("scalar is zero in aggregation\n");
12454  SCIPABORT();
12455  return SCIP_INVALID; /*lint !e527*/
12456  }
12457 
12459  /**@todo get the sides of the corresponding linear constraint */
12460  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12461  SCIPABORT();
12462  return SCIP_INVALID; /*lint !e527*/
12463 
12464  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12465  assert(var->negatedvar != NULL);
12467  assert(var->negatedvar->negatedvar == var);
12468  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12469 
12470  default:
12471  SCIPerrorMessage("unknown variable status\n");
12472  SCIPABORT();
12473  return SCIP_INVALID; /*lint !e527*/
12474  }
12475 }
12476 
12477 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12478  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12479  */
12481  SCIP_VAR* var, /**< problem variable */
12482  SCIP_SET* set /**< global SCIP settings */
12483  )
12484 {
12485  assert(var != NULL);
12486  assert(set != NULL);
12487  assert(var->scip == set->scip);
12488 
12489  /* get bounds of attached variables */
12490  switch( SCIPvarGetStatus(var) )
12491  {
12493  assert(var->data.original.transvar != NULL);
12494  return SCIPvarGetUbLP(var->data.original.transvar, set);
12495 
12496  case SCIP_VARSTATUS_COLUMN:
12497  assert(var->data.col != NULL);
12498  return SCIPcolGetUb(var->data.col);
12499 
12500  case SCIP_VARSTATUS_LOOSE:
12501  case SCIP_VARSTATUS_FIXED:
12502  return var->locdom.ub;
12503 
12504  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12505  assert(var->data.aggregate.var != NULL);
12506  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12507  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12508  {
12509  return SCIPsetInfinity(set);
12510  }
12511  if( var->data.aggregate.scalar > 0.0 )
12512  {
12513  /* a > 0 -> get upper bound of y */
12514  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12515  }
12516  else if( var->data.aggregate.scalar < 0.0 )
12517  {
12518  /* a < 0 -> get lower bound of y */
12519  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12520  }
12521  else
12522  {
12523  SCIPerrorMessage("scalar is zero in aggregation\n");
12524  SCIPABORT();
12525  return SCIP_INVALID; /*lint !e527*/
12526  }
12527 
12529  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12530  SCIPABORT();
12531  return SCIP_INVALID; /*lint !e527*/
12532 
12533  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12534  assert(var->negatedvar != NULL);
12536  assert(var->negatedvar->negatedvar == var);
12537  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12538 
12539  default:
12540  SCIPerrorMessage("unknown variable status\n");
12541  SCIPABORT();
12542  return SCIP_INVALID; /*lint !e527*/
12543  }
12544 }
12545 
12546 /** gets primal LP solution value of variable */
12548  SCIP_VAR* var /**< problem variable */
12549  )
12550 {
12551  assert(var != NULL);
12552 
12553  switch( SCIPvarGetStatus(var) )
12554  {
12556  if( var->data.original.transvar == NULL )
12557  return SCIP_INVALID;
12558  return SCIPvarGetLPSol(var->data.original.transvar);
12559 
12560  case SCIP_VARSTATUS_LOOSE:
12561  return SCIPvarGetBestBoundLocal(var);
12562 
12563  case SCIP_VARSTATUS_COLUMN:
12564  assert(var->data.col != NULL);
12565  return SCIPcolGetPrimsol(var->data.col);
12566 
12567  case SCIP_VARSTATUS_FIXED:
12568  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12569  return var->locdom.lb;
12570 
12572  {
12573  SCIP_Real lpsolval;
12574 
12575  assert(var->data.aggregate.var != NULL);
12576  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12577 
12578  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12579  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12580  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12581  * (or is called by) a public interface method; instead, we only assert that values are finite
12582  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12583  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12584  */
12585  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12586  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12587  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12588  }
12590  {
12591  SCIP_Real primsol;
12592  int i;
12593 
12594  assert(!var->donotmultaggr);
12595  assert(var->data.multaggr.vars != NULL);
12596  assert(var->data.multaggr.scalars != NULL);
12597  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12598  * assert(var->data.multaggr.nvars >= 2);
12599  */
12600  primsol = var->data.multaggr.constant;
12601  for( i = 0; i < var->data.multaggr.nvars; ++i )
12602  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12603  return primsol;
12604  }
12605  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12606  assert(var->negatedvar != NULL);
12608  assert(var->negatedvar->negatedvar == var);
12609  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12610 
12611  default:
12612  SCIPerrorMessage("unknown variable status\n");
12613  SCIPABORT();
12614  return SCIP_INVALID; /*lint !e527*/
12615  }
12616 }
12617 
12618 /** gets primal NLP solution value of variable */
12620  SCIP_VAR* var /**< problem variable */
12621  )
12622 {
12623  SCIP_Real solval;
12624  int i;
12625 
12626  assert(var != NULL);
12627 
12628  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12629  switch( SCIPvarGetStatus(var) )
12630  {
12632  return SCIPvarGetNLPSol(var->data.original.transvar);
12633 
12634  case SCIP_VARSTATUS_LOOSE:
12635  case SCIP_VARSTATUS_COLUMN:
12636  return var->nlpsol;
12637 
12638  case SCIP_VARSTATUS_FIXED:
12639  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12640  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12641  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12642  return SCIPvarGetLbGlobal(var);
12643 
12644  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12645  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12646  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12647 
12649  solval = var->data.multaggr.constant;
12650  for( i = 0; i < var->data.multaggr.nvars; ++i )
12651  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12652  return solval;
12653 
12655  solval = SCIPvarGetNLPSol(var->negatedvar);
12656  return var->data.negate.constant - solval;
12657 
12658  default:
12659  SCIPerrorMessage("unknown variable status\n");
12660  SCIPABORT();
12661  return SCIP_INVALID; /*lint !e527*/
12662  }
12663 }
12664 
12665 /** gets pseudo solution value of variable at current node */
12666 static
12668  SCIP_VAR* var /**< problem variable */
12669  )
12670 {
12671  SCIP_Real pseudosol;
12672  int i;
12673 
12674  assert(var != NULL);
12675 
12676  switch( SCIPvarGetStatus(var) )
12677  {
12679  if( var->data.original.transvar == NULL )
12680  return SCIP_INVALID;
12682 
12683  case SCIP_VARSTATUS_LOOSE:
12684  case SCIP_VARSTATUS_COLUMN:
12685  return SCIPvarGetBestBoundLocal(var);
12686 
12687  case SCIP_VARSTATUS_FIXED:
12688  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12689  return var->locdom.lb;
12690 
12692  {
12693  SCIP_Real pseudosolval;
12694  assert(var->data.aggregate.var != NULL);
12695  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12696  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12697  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12698  * (or is called by) a public interface method; instead, we only assert that values are finite
12699  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12700  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12701  */
12702  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12703  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12704  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12705  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12706  }
12708  assert(!var->donotmultaggr);
12709  assert(var->data.multaggr.vars != NULL);
12710  assert(var->data.multaggr.scalars != NULL);
12711  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12712  * assert(var->data.multaggr.nvars >= 2);
12713  */
12714  pseudosol = var->data.multaggr.constant;
12715  for( i = 0; i < var->data.multaggr.nvars; ++i )
12716  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12717  return pseudosol;
12718 
12719  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12720  assert(var->negatedvar != NULL);
12722  assert(var->negatedvar->negatedvar == var);
12723  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12724 
12725  default:
12726  SCIPerrorMessage("unknown variable status\n");
12727  SCIPABORT();
12728  return SCIP_INVALID; /*lint !e527*/
12729  }
12730 }
12731 
12732 /** gets current LP or pseudo solution value of variable */
12734  SCIP_VAR* var, /**< problem variable */
12735  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12736  )
12737 {
12738  if( getlpval )
12739  return SCIPvarGetLPSol(var);
12740  else
12741  return SCIPvarGetPseudoSol(var);
12742 }
12743 
12744 /** remembers the current solution as root solution in the problem variables */
12745 void SCIPvarStoreRootSol(
12746  SCIP_VAR* var, /**< problem variable */
12747  SCIP_Bool roothaslp /**< is the root solution from LP? */
12748  )
12749 {
12750  assert(var != NULL);
12751 
12752  var->rootsol = SCIPvarGetSol(var, roothaslp);
12753 }
12754 
12755 /** updates the current solution as best root solution of the given variable if it is better */
12757  SCIP_VAR* var, /**< problem variable */
12758  SCIP_SET* set, /**< global SCIP settings */
12759  SCIP_Real rootsol, /**< root solution value */
12760  SCIP_Real rootredcost, /**< root reduced cost */
12761  SCIP_Real rootlpobjval /**< objective value of the root LP */
12762  )
12763 {
12764  assert(var != NULL);
12765  assert(set != NULL);
12766  assert(var->scip == set->scip);
12767 
12768  /* if reduced cost are zero nothing to update */
12769  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12770  return;
12771 
12772  /* check if we have already a best combination stored */
12773  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12774  {
12775  SCIP_Real currcutoffbound;
12776  SCIP_Real cutoffbound;
12777  SCIP_Real bound;
12778 
12779  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12780  * root reduced cost, and root LP objective value combination
12781  */
12782  if( var->bestrootredcost > 0.0 )
12783  bound = SCIPvarGetUbGlobal(var);
12784  else
12785  bound = SCIPvarGetLbGlobal(var);
12786 
12787  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12788 
12789  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12790  * cost, and root LP objective value combination
12791  */
12792  if( rootredcost > 0.0 )
12793  bound = SCIPvarGetUbGlobal(var);
12794  else
12795  bound = SCIPvarGetLbGlobal(var);
12796 
12797  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12798 
12799  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12800  if( cutoffbound > currcutoffbound )
12801  {
12802  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12803  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12804 
12805  var->bestrootsol = rootsol;
12806  var->bestrootredcost = rootredcost;
12807  var->bestrootlpobjval = rootlpobjval;
12808  }
12809  }
12810  else
12811  {
12812  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12813  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12814  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12815  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12816 
12817  var->bestrootsol = rootsol;
12818  var->bestrootredcost = rootredcost;
12819  var->bestrootlpobjval = rootlpobjval;
12820  }
12821 }
12822 
12823 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12824  * completely solved, zero is returned
12825  */
12827  SCIP_VAR* var /**< problem variable */
12828  )
12829 {
12830  SCIP_Real rootsol;
12831  int i;
12832 
12833  assert(var != NULL);
12834 
12835  switch( SCIPvarGetStatus(var) )
12836  {
12838  if( var->data.original.transvar == NULL )
12839  return 0.0;
12840  return SCIPvarGetRootSol(var->data.original.transvar);
12841 
12842  case SCIP_VARSTATUS_LOOSE:
12843  case SCIP_VARSTATUS_COLUMN:
12844  return var->rootsol;
12845 
12846  case SCIP_VARSTATUS_FIXED:
12847  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12848  return var->locdom.lb;
12849 
12851  assert(var->data.aggregate.var != NULL);
12852  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12853  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12854  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12855  * (or is called by) a public interface method; instead, we only assert that values are finite
12856  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12857  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12858  */
12862 
12864  assert(!var->donotmultaggr);
12865  assert(var->data.multaggr.vars != NULL);
12866  assert(var->data.multaggr.scalars != NULL);
12867  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12868  * assert(var->data.multaggr.nvars >= 2);
12869  */
12870  rootsol = var->data.multaggr.constant;
12871  for( i = 0; i < var->data.multaggr.nvars; ++i )
12872  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12873  return rootsol;
12874 
12875  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12876  assert(var->negatedvar != NULL);
12878  assert(var->negatedvar->negatedvar == var);
12879  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12880 
12881  default:
12882  SCIPerrorMessage("unknown variable status\n");
12883  SCIPABORT();
12884  return SCIP_INVALID; /*lint !e527*/
12885  }
12886 }
12887 
12888 /** returns for given variable the reduced cost */
12889 static
12891  SCIP_VAR* var, /**< problem variable */
12892  SCIP_SET* set, /**< global SCIP settings */
12893  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12894  SCIP_STAT* stat, /**< problem statistics */
12895  SCIP_LP* lp /**< current LP data */
12896  )
12897 {
12899  {
12900  SCIP_COL* col;
12901  SCIP_Real primsol;
12902  SCIP_BASESTAT basestat;
12903  SCIP_Bool lpissolbasic;
12904 
12905  col = SCIPvarGetCol(var);
12906  assert(col != NULL);
12907 
12908  basestat = SCIPcolGetBasisStatus(col);
12909  lpissolbasic = SCIPlpIsSolBasic(lp);
12910  primsol = SCIPcolGetPrimsol(col);
12911 
12912  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12913  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12914  {
12915  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12916 
12917  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12918  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12920  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12921  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12922  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12923 
12924  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12925  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12926  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12927  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12928  return redcost;
12929  else
12930  return 0.0;
12931  }
12932 
12933  return 0.0;
12934  }
12935 
12936  return 0.0;
12937 }
12938 
12939 #define MAX_CLIQUELENGTH 50
12940 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12941  * the binary variable is fixed to the given value
12942  */
12944  SCIP_VAR* var, /**< problem variable */
12945  SCIP_SET* set, /**< global SCIP settings */
12946  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12947  SCIP_STAT* stat, /**< problem statistics */
12948  SCIP_PROB* prob, /**< transformed problem, or NULL */
12949  SCIP_LP* lp /**< current LP data */
12950  )
12951 {
12952  SCIP_Real implredcost;
12953  int ncliques;
12954  int nvars;
12955 
12956  assert(SCIPvarIsBinary(var));
12957  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12958 
12959  /* get reduced cost of given variable */
12960  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12961 
12962 #ifdef SCIP_MORE_DEBUG
12963  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12964 #endif
12965 
12966  /* the following algorithm is expensive */
12967  ncliques = SCIPvarGetNCliques(var, varfixing);
12968 
12969  if( ncliques > 0 )
12970  {
12971  SCIP_CLIQUE** cliques;
12972  SCIP_CLIQUE* clique;
12973  SCIP_VAR** clqvars;
12974  SCIP_VAR** probvars;
12975  SCIP_VAR* clqvar;
12976  SCIP_Bool* clqvalues;
12977  int* entries;
12978  int* ids;
12979  SCIP_Real redcost;
12980  SCIP_Bool cleanedup;
12981  int nclqvars;
12982  int nentries;
12983  int nids;
12984  int id;
12985  int c;
12986  int v;
12987 
12988  assert(prob != NULL);
12989  assert(SCIPprobIsTransformed(prob));
12990 
12991  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12992 
12993  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
12994  nids = 0;
12995  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
12996 
12997  cliques = SCIPvarGetCliques(var, varfixing);
12998  assert(cliques != NULL);
12999 
13000  for( c = ncliques - 1; c >= 0; --c )
13001  {
13002  clique = cliques[c];
13003  assert(clique != NULL);
13004  nclqvars = SCIPcliqueGetNVars(clique);
13005  assert(nclqvars > 0);
13006 
13007  if( nclqvars > MAX_CLIQUELENGTH )
13008  continue;
13009 
13010  clqvars = SCIPcliqueGetVars(clique);
13011  clqvalues = SCIPcliqueGetValues(clique);
13012  assert(clqvars != NULL);
13013  assert(clqvalues != NULL);
13014 
13015  cleanedup = SCIPcliqueIsCleanedUp(clique);
13016 
13017  for( v = nclqvars - 1; v >= 0; --v )
13018  {
13019  clqvar = clqvars[v];
13020  assert(clqvar != NULL);
13021 
13022  /* ignore binary variable which are fixed */
13023  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13024  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13025  {
13026  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13027  assert(0 < probindex && probindex < nentries);
13028 
13029 #if 0
13030  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13031  * can appear since there is no guarantee that all these infeasible bounds were found
13032  */
13033  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13034 #endif
13035  if( entries[probindex] == 0 )
13036  {
13037  ids[nids] = probindex;
13038  ++nids;
13039 
13040  /* mark variable as visited */
13041  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13042  }
13043  }
13044  }
13045  }
13046 
13047  probvars = SCIPprobGetVars(prob);
13048  assert(probvars != NULL);
13049 
13050  /* add all implied reduced cost */
13051  for( v = nids - 1; v >= 0; --v )
13052  {
13053  id = ids[v];
13054  assert(0 < id && id < nentries);
13055  assert(entries[id] != 0);
13056  assert(probvars[id - 1] != NULL);
13057  assert(SCIPvarIsActive(probvars[id - 1]));
13058  assert(SCIPvarIsBinary(probvars[id - 1]));
13059  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13060 
13061  if( (entries[id] > 0) != varfixing )
13062  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13063  else
13064  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13065 
13066  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13067  implredcost += redcost;
13068 
13069  /* reset entries clear buffer array */
13070  entries[id] = 0;
13071  }
13072 
13073  SCIPsetFreeCleanBufferArray(set, &entries);
13074  SCIPsetFreeBufferArray(set, &ids);
13075  }
13076 
13077 #ifdef SCIP_MORE_DEBUG
13078  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13079  implredcost);
13080 #endif
13081 
13082  /* collect non-binary implication information */
13083  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13084 
13085  if( nvars > 0 )
13086  {
13087  SCIP_VAR** vars;
13088  SCIP_VAR* implvar;
13089  SCIP_COL* col;
13090  SCIP_Real* bounds;
13091  SCIP_BOUNDTYPE* boundtypes;
13092  SCIP_Real redcost;
13093  SCIP_Real lb;
13094  SCIP_Real ub;
13095  SCIP_Bool lpissolbasic;
13096  int v;
13097 
13098  vars = SCIPimplicsGetVars(var->implics, varfixing);
13099  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13100  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13101  lpissolbasic = SCIPlpIsSolBasic(lp);
13102 
13103  for( v = nvars - 1; v >= 0; --v )
13104  {
13105  implvar = vars[v];
13106  assert(implvar != NULL);
13107 
13108  lb = SCIPvarGetLbLocal(implvar);
13109  ub = SCIPvarGetUbLocal(implvar);
13110 
13111  /* ignore binary variable which are fixed or not of column status */
13112  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13113  continue;
13114 
13115  col = SCIPvarGetCol(implvar);
13116  assert(col != NULL);
13117  redcost = 0.0;
13118 
13119  /* solved lp with basis information or not? */
13120  if( lpissolbasic )
13121  {
13122  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13123 
13124  /* check if the implication is not not yet applied */
13125  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13126  {
13127  redcost = SCIPcolGetRedcost(col, stat, lp);
13128  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13129 
13130  if( !varfixing )
13131  redcost *= (lb - bounds[v]);
13132  else
13133  redcost *= (bounds[v] - lb);
13134  }
13135  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13136  {
13137  redcost = SCIPcolGetRedcost(col, stat, lp);
13138  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13139 
13140  if( varfixing )
13141  redcost *= (bounds[v] - ub);
13142  else
13143  redcost *= (ub - bounds[v]);
13144  }
13145  }
13146  else
13147  {
13148  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13149 
13150  /* check if the implication is not not yet applied */
13151  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13152  {
13153  redcost = SCIPcolGetRedcost(col, stat, lp);
13154  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13155 
13156  if( varfixing )
13157  redcost *= (lb - bounds[v]);
13158  else
13159  redcost *= (bounds[v] - lb);
13160  }
13161  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13162  {
13163  redcost = SCIPcolGetRedcost(col, stat, lp);
13164  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13165 
13166  if( varfixing )
13167  redcost *= (bounds[v] - ub);
13168  else
13169  redcost *= (ub - bounds[v]);
13170  }
13171  }
13172 
13173  /* improve implied reduced cost */
13174  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13175  implredcost += redcost;
13176  }
13177  }
13178 
13179 #ifdef SCIP_MORE_DEBUG
13180  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13181  SCIPvarGetName(var), ncliques, nvars, implredcost);
13182 #endif
13183 
13184  return implredcost;
13185 }
13186 
13187 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13188  * the root relaxation is not yet completely solved, zero is returned
13189  */
13191  SCIP_VAR* var /**< problem variable */
13192  )
13193 {
13194  SCIP_Real rootsol;
13195  int i;
13196 
13197  assert(var != NULL);
13198 
13199  switch( SCIPvarGetStatus(var) )
13200  {
13202  if( var->data.original.transvar == NULL )
13203  return 0.0;
13205 
13206  case SCIP_VARSTATUS_LOOSE:
13207  case SCIP_VARSTATUS_COLUMN:
13208  return var->bestrootsol;
13209 
13210  case SCIP_VARSTATUS_FIXED:
13211  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13212  return var->locdom.lb;
13213 
13215  assert(var->data.aggregate.var != NULL);
13216  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13217  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13218  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13219  * (or is called by) a public interface method; instead, we only assert that values are finite
13220  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13221  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13222  */
13226 
13228  assert(!var->donotmultaggr);
13229  assert(var->data.multaggr.vars != NULL);
13230  assert(var->data.multaggr.scalars != NULL);
13231  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13232  * assert(var->data.multaggr.nvars >= 2);
13233  */
13234  rootsol = var->data.multaggr.constant;
13235  for( i = 0; i < var->data.multaggr.nvars; ++i )
13236  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13237  return rootsol;
13238 
13239  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13240  assert(var->negatedvar != NULL);
13242  assert(var->negatedvar->negatedvar == var);
13243  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13244 
13245  default:
13246  SCIPerrorMessage("unknown variable status\n");
13247  SCIPABORT();
13248  return 0.0; /*lint !e527*/
13249  }
13250 }
13251 
13252 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13253  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13254  * returned
13255  */
13257  SCIP_VAR* var /**< problem variable */
13258  )
13259 {
13260  assert(var != NULL);
13261 
13262  switch( SCIPvarGetStatus(var) )
13263  {
13265  if( var->data.original.transvar == NULL )
13266  return SCIP_INVALID;
13268 
13269  case SCIP_VARSTATUS_LOOSE:
13270  case SCIP_VARSTATUS_COLUMN:
13271  return var->bestrootredcost;
13272 
13273  case SCIP_VARSTATUS_FIXED:
13277  return 0.0;
13278 
13279  default:
13280  SCIPerrorMessage("unknown variable status\n");
13281  SCIPABORT();
13282  return 0.0; /*lint !e527*/
13283  }
13284 }
13285 
13286 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13287  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13288  * SCIP_INVALID is returned
13289  */
13291  SCIP_VAR* var /**< problem variable */
13292  )
13293 {
13294  assert(var != NULL);
13295 
13296  switch( SCIPvarGetStatus(var) )
13297  {
13299  if( var->data.original.transvar == NULL )
13300  return SCIP_INVALID;
13302 
13303  case SCIP_VARSTATUS_LOOSE:
13304  case SCIP_VARSTATUS_COLUMN:
13305  return var->bestrootlpobjval;
13306 
13307  case SCIP_VARSTATUS_FIXED:
13311  return SCIP_INVALID;
13312 
13313  default:
13314  SCIPerrorMessage("unknown variable status\n");
13315  SCIPABORT();
13316  return SCIP_INVALID; /*lint !e527*/
13317  }
13318 }
13319 
13320 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13322  SCIP_VAR* var, /**< problem variable */
13323  SCIP_Real rootsol, /**< root solution value */
13324  SCIP_Real rootredcost, /**< root reduced cost */
13325  SCIP_Real rootlpobjval /**< objective value of the root LP */
13326  )
13327 {
13328  assert(var != NULL);
13329 
13330  var->bestrootsol = rootsol;
13331  var->bestrootredcost = rootredcost;
13332  var->bestrootlpobjval = rootlpobjval;
13333 }
13334 
13335 /** stores the solution value as relaxation solution in the problem variable */
13337  SCIP_VAR* var, /**< problem variable */
13338  SCIP_SET* set, /**< global SCIP settings */
13339  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13340  SCIP_Real solval, /**< solution value in the current relaxation solution */
13341  SCIP_Bool updateobj /**< should the objective value be updated? */
13342  )
13343 {
13344  assert(var != NULL);
13345  assert(relaxation != NULL);
13346  assert(set != NULL);
13347  assert(var->scip == set->scip);
13348 
13349  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13350  switch( SCIPvarGetStatus(var) )
13351  {
13353  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13354  break;
13355 
13356  case SCIP_VARSTATUS_LOOSE:
13357  case SCIP_VARSTATUS_COLUMN:
13358  if( updateobj )
13359  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13360  var->relaxsol = solval;
13361  break;
13362 
13363  case SCIP_VARSTATUS_FIXED:
13364  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13365  {
13366  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13367  SCIPvarGetName(var), var->glbdom.lb, solval);
13368  return SCIP_INVALIDDATA;
13369  }
13370  break;
13371 
13372  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13373  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13374  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13375  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13376  break;
13378  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13379  return SCIP_INVALIDDATA;
13380 
13382  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13383  break;
13384 
13385  default:
13386  SCIPerrorMessage("unknown variable status\n");
13387  return SCIP_INVALIDDATA;
13388  }
13389 
13390  return SCIP_OKAY;
13391 }
13392 
13393 /** returns the solution value of the problem variable in the relaxation solution
13394  *
13395  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13396  */
13398  SCIP_VAR* var, /**< problem variable */
13399  SCIP_SET* set /**< global SCIP settings */
13400  )
13401 {
13402  SCIP_Real solvalsum;
13403  SCIP_Real solval;
13404  int i;
13405 
13406  assert(var != NULL);
13407  assert(set != NULL);
13408  assert(var->scip == set->scip);
13409 
13410  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13411  switch( SCIPvarGetStatus(var) )
13412  {
13414  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13415 
13416  case SCIP_VARSTATUS_LOOSE:
13417  case SCIP_VARSTATUS_COLUMN:
13418  return var->relaxsol;
13419 
13420  case SCIP_VARSTATUS_FIXED:
13421  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13422  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13423  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13424  return SCIPvarGetLbGlobal(var);
13425 
13426  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13427  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13428  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13429  {
13430  if( var->data.aggregate.scalar * solval > 0.0 )
13431  return SCIPsetInfinity(set);
13432  if( var->data.aggregate.scalar * solval < 0.0 )
13433  return -SCIPsetInfinity(set);
13434  }
13435  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13436 
13438  solvalsum = var->data.multaggr.constant;
13439  for( i = 0; i < var->data.multaggr.nvars; ++i )
13440  {
13441  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13442  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13443  {
13444  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13445  return SCIPsetInfinity(set);
13446  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13447  return -SCIPsetInfinity(set);
13448  }
13449  solvalsum += var->data.multaggr.scalars[i] * solval;
13450  }
13451  return solvalsum;
13452 
13454  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13455  if( SCIPsetIsInfinity(set, solval) )
13456  return -SCIPsetInfinity(set);
13457  if( SCIPsetIsInfinity(set, -solval) )
13458  return SCIPsetInfinity(set);
13459  return var->data.negate.constant - solval;
13460 
13461  default:
13462  SCIPerrorMessage("unknown variable status\n");
13463  SCIPABORT();
13464  return SCIP_INVALID; /*lint !e527*/
13465  }
13466 }
13467 
13468 /** returns the solution value of the transformed problem variable in the relaxation solution */
13470  SCIP_VAR* var /**< problem variable */
13471  )
13472 {
13473  assert(var != NULL);
13475 
13476  return var->relaxsol;
13477 }
13478 
13479 /** stores the solution value as NLP solution in the problem variable */
13481  SCIP_VAR* var, /**< problem variable */
13482  SCIP_SET* set, /**< global SCIP settings */
13483  SCIP_Real solval /**< solution value in the current NLP solution */
13484  )
13485 {
13486  assert(var != NULL);
13487  assert(set != NULL);
13488  assert(var->scip == set->scip);
13489 
13490  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13491  switch( SCIPvarGetStatus(var) )
13492  {
13494  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13495  break;
13496 
13497  case SCIP_VARSTATUS_LOOSE:
13498  case SCIP_VARSTATUS_COLUMN:
13499  var->nlpsol = solval;
13500  break;
13501 
13502  case SCIP_VARSTATUS_FIXED:
13503  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13504  {
13505  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13506  SCIPvarGetName(var), var->glbdom.lb, solval);
13507  SCIPABORT();
13508  return SCIP_INVALIDCALL; /*lint !e527*/
13509  }
13510  break;
13511 
13512  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13513  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13514  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13515  break;
13516 
13518  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13519  SCIPABORT();
13520  return SCIP_INVALIDCALL; /*lint !e527*/
13521 
13523  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13524  break;
13525 
13526  default:
13527  SCIPerrorMessage("unknown variable status\n");
13528  SCIPABORT();
13529  return SCIP_ERROR; /*lint !e527*/
13530  }
13531 
13532  return SCIP_OKAY;
13533 }
13534 
13535 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13537  SCIP_VAR* var /**< problem variable */
13538  )
13539 {
13540  SCIP_Real avgsol;
13541  int i;
13542 
13543  assert(var != NULL);
13544 
13545  switch( SCIPvarGetStatus(var) )
13546  {
13548  if( var->data.original.transvar == NULL )
13549  return 0.0;
13550  return SCIPvarGetAvgSol(var->data.original.transvar);
13551 
13552  case SCIP_VARSTATUS_LOOSE:
13553  case SCIP_VARSTATUS_COLUMN:
13554  avgsol = var->primsolavg;
13555  avgsol = MAX(avgsol, var->glbdom.lb);
13556  avgsol = MIN(avgsol, var->glbdom.ub);
13557  return avgsol;
13558 
13559  case SCIP_VARSTATUS_FIXED:
13560  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13561  return var->locdom.lb;
13562 
13564  assert(var->data.aggregate.var != NULL);
13565  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13566  + var->data.aggregate.constant;
13567 
13569  assert(!var->donotmultaggr);
13570  assert(var->data.multaggr.vars != NULL);
13571  assert(var->data.multaggr.scalars != NULL);
13572  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13573  * assert(var->data.multaggr.nvars >= 2);
13574  */
13575  avgsol = var->data.multaggr.constant;
13576  for( i = 0; i < var->data.multaggr.nvars; ++i )
13577  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13578  return avgsol;
13579 
13580  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13581  assert(var->negatedvar != NULL);
13583  assert(var->negatedvar->negatedvar == var);
13584  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13585 
13586  default:
13587  SCIPerrorMessage("unknown variable status\n");
13588  SCIPABORT();
13589  return 0.0; /*lint !e527*/
13590  }
13591 }
13592 
13593 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13594  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13595  */
13597  SCIP_VAR* var, /**< active problem variable */
13598  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13599  SCIP_SET* set, /**< global SCIP settings */
13600  SCIP_STAT* stat, /**< problem statistics */
13601  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13602  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13603  )
13604 {
13605  int nvlbs;
13606 
13607  assert(var != NULL);
13608  assert(stat != NULL);
13609  assert(set != NULL);
13610  assert(var->scip == set->scip);
13611  assert(closestvlb != NULL);
13612  assert(closestvlbidx != NULL);
13613 
13614  *closestvlbidx = -1;
13615  *closestvlb = SCIP_REAL_MIN;
13616 
13617  nvlbs = SCIPvarGetNVlbs(var);
13618  if( nvlbs > 0 )
13619  {
13620  SCIP_VAR** vlbvars;
13621  SCIP_Real* vlbcoefs;
13622  SCIP_Real* vlbconsts;
13623  int i;
13624 
13625  vlbvars = SCIPvarGetVlbVars(var);
13626  vlbcoefs = SCIPvarGetVlbCoefs(var);
13627  vlbconsts = SCIPvarGetVlbConstants(var);
13628 
13629  /* check for cached values */
13630  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13631  {
13632  i = var->closestvlbidx;
13633  assert(0 <= i && i < nvlbs);
13634  assert(SCIPvarIsActive(vlbvars[i]));
13635  *closestvlbidx = i;
13636  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13637  }
13638  else
13639  {
13640  /* search best VUB */
13641  for( i = 0; i < nvlbs; i++ )
13642  {
13643  if( SCIPvarIsActive(vlbvars[i]) )
13644  {
13645  SCIP_Real vlbsol;
13646 
13647  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13648  if( vlbsol > *closestvlb )
13649  {
13650  *closestvlb = vlbsol;
13651  *closestvlbidx = i;
13652  }
13653  }
13654  }
13655 
13656  if( sol == NULL )
13657  {
13658  /* update cached value */
13659  if( var->closestvblpcount != stat->lpcount )
13660  var->closestvubidx = -1;
13661  var->closestvlbidx = *closestvlbidx;
13662  var->closestvblpcount = stat->lpcount;
13663  }
13664  }
13665  }
13666 }
13667 
13668 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13669  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13670  */
13672  SCIP_VAR* var, /**< active problem variable */
13673  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13674  SCIP_SET* set, /**< global SCIP settings */
13675  SCIP_STAT* stat, /**< problem statistics */
13676  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13677  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13678  )
13679 {
13680  int nvubs;
13681 
13682  assert(var != NULL);
13683  assert(set != NULL);
13684  assert(var->scip == set->scip);
13685  assert(closestvub != NULL);
13686  assert(closestvubidx != NULL);
13687 
13688  *closestvubidx = -1;
13689  *closestvub = SCIP_REAL_MAX;
13690 
13691  nvubs = SCIPvarGetNVubs(var);
13692  if( nvubs > 0 )
13693  {
13694  SCIP_VAR** vubvars;
13695  SCIP_Real* vubcoefs;
13696  SCIP_Real* vubconsts;
13697  int i;
13698 
13699  vubvars = SCIPvarGetVubVars(var);
13700  vubcoefs = SCIPvarGetVubCoefs(var);
13701  vubconsts = SCIPvarGetVubConstants(var);
13702 
13703  /* check for cached values */
13704  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13705  {
13706  i = var->closestvubidx;
13707  assert(0 <= i && i < nvubs);
13708  assert(SCIPvarIsActive(vubvars[i]));
13709  *closestvubidx = i;
13710  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13711  }
13712  else
13713  {
13714  /* search best VUB */
13715  for( i = 0; i < nvubs; i++ )
13716  {
13717  if( SCIPvarIsActive(vubvars[i]) )
13718  {
13719  SCIP_Real vubsol;
13720 
13721  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13722  if( vubsol < *closestvub )
13723  {
13724  *closestvub = vubsol;
13725  *closestvubidx = i;
13726  }
13727  }
13728  }
13729 
13730  if( sol == NULL )
13731  {
13732  /* update cached value */
13733  if( var->closestvblpcount != stat->lpcount )
13734  var->closestvlbidx = -1;
13735  var->closestvubidx = *closestvubidx;
13736  var->closestvblpcount = stat->lpcount;
13737  }
13738  }
13739  }
13740 }
13741 
13742 /** resolves variable to columns and adds them with the coefficient to the row */
13744  SCIP_VAR* var, /**< problem variable */
13745  BMS_BLKMEM* blkmem, /**< block memory */
13746  SCIP_SET* set, /**< global SCIP settings */
13747  SCIP_STAT* stat, /**< problem statistics */
13748  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13749  SCIP_PROB* prob, /**< problem data */
13750  SCIP_LP* lp, /**< current LP data */
13751  SCIP_ROW* row, /**< LP row */
13752  SCIP_Real val /**< value of coefficient */
13753  )
13754 {
13755  int i;
13756 
13757  assert(var != NULL);
13758  assert(set != NULL);
13759  assert(var->scip == set->scip);
13760  assert(row != NULL);
13761  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13762 
13763  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13764 
13765  if ( SCIPsetIsZero(set, val) )
13766  return SCIP_OKAY;
13767 
13768  switch( SCIPvarGetStatus(var) )
13769  {
13771  if( var->data.original.transvar == NULL )
13772  {
13773  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13774  return SCIP_INVALIDDATA;
13775  }
13776  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13777  return SCIP_OKAY;
13778 
13779  case SCIP_VARSTATUS_LOOSE:
13780  /* add globally fixed variables as constant */
13781  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13782  {
13783  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13784  return SCIP_OKAY;
13785  }
13786  /* convert loose variable into column */
13787  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13788  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13789  /*lint -fallthrough*/
13790 
13791  case SCIP_VARSTATUS_COLUMN:
13792  assert(var->data.col != NULL);
13793  assert(var->data.col->var == var);
13794  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13795  return SCIP_OKAY;
13796 
13797  case SCIP_VARSTATUS_FIXED:
13798  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13799  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13800  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13801  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13802  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13803  return SCIP_OKAY;
13804 
13806  assert(var->data.aggregate.var != NULL);
13807  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13808  row, var->data.aggregate.scalar * val) );
13809  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13810  return SCIP_OKAY;
13811 
13813  assert(!var->donotmultaggr);
13814  assert(var->data.multaggr.vars != NULL);
13815  assert(var->data.multaggr.scalars != NULL);
13816  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13817  * assert(var->data.multaggr.nvars >= 2);
13818  */
13819  for( i = 0; i < var->data.multaggr.nvars; ++i )
13820  {
13821  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13822  row, var->data.multaggr.scalars[i] * val) );
13823  }
13824  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13825  return SCIP_OKAY;
13826 
13827  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13828  assert(var->negatedvar != NULL);
13830  assert(var->negatedvar->negatedvar == var);
13831  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13832  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13833  return SCIP_OKAY;
13834 
13835  default:
13836  SCIPerrorMessage("unknown variable status\n");
13837  return SCIP_INVALIDDATA;
13838  }
13839 }
13840 
13841 /* optionally, define this compiler flag to write complete variable histories to a file */
13842 #ifdef SCIP_HISTORYTOFILE
13843 SCIP_Longint counter = 0l;
13844 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13845 #include "scip/scip.h"
13846 #endif
13847 
13848 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13849  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13850  */
13852  SCIP_VAR* var, /**< problem variable */
13853  SCIP_SET* set, /**< global SCIP settings */
13854  SCIP_STAT* stat, /**< problem statistics */
13855  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13856  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13857  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13858  )
13859 {
13860  SCIP_Real oldrootpseudocosts;
13861  assert(var != NULL);
13862  assert(set != NULL);
13863  assert(var->scip == set->scip);
13864  assert(stat != NULL);
13865 
13866  /* check if history statistics should be collected for a variable */
13867  if( !stat->collectvarhistory )
13868  return SCIP_OKAY;
13869 
13870  switch( SCIPvarGetStatus(var) )
13871  {
13873  if( var->data.original.transvar == NULL )
13874  {
13875  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13876  return SCIP_INVALIDDATA;
13877  }
13878  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13879  return SCIP_OKAY;
13880 
13881  case SCIP_VARSTATUS_LOOSE:
13882  case SCIP_VARSTATUS_COLUMN:
13883  /* store old pseudo-costs for root LP best-estimate update */
13884  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13885 
13886  /* update history */
13887  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13888  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13889  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13890  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13891 
13892  /* update root LP best-estimate */
13893  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13894 
13895  /* append history to file */
13896 #ifdef SCIP_HISTORYTOFILE
13897  {
13898  FILE* f;
13899  char filename[256];
13900  SCIP_NODE* currentnode;
13901  SCIP_NODE* parentnode;
13902  currentnode = SCIPgetFocusNode(set->scip);
13903  parentnode = SCIPnodeGetParent(currentnode);
13904 
13905  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13906  f = fopen(filename, "a");
13907  if( NULL != f )
13908  {
13909  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13910  ++counter,
13911  SCIPvarGetName(var),
13912  SCIPnodeGetNumber(currentnode),
13913  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13914  SCIPgetNLPIterations(set->scip),
13915  SCIPgetDepth(set->scip),
13916  objdelta,
13917  solvaldelta);
13918  fclose(f);
13919  }
13920  }
13921 #endif
13922  return SCIP_OKAY;
13923 
13924  case SCIP_VARSTATUS_FIXED:
13925  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13926  return SCIP_INVALIDDATA;
13927 
13929  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13931  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13932  return SCIP_OKAY;
13933 
13935  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13936  return SCIP_INVALIDDATA;
13937 
13939  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13940  return SCIP_OKAY;
13941 
13942  default:
13943  SCIPerrorMessage("unknown variable status\n");
13944  return SCIP_INVALIDDATA;
13945  }
13946 }
13947 
13948 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13950  SCIP_VAR* var, /**< problem variable */
13951  SCIP_STAT* stat, /**< problem statistics */
13952  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13953  )
13954 {
13955  SCIP_BRANCHDIR dir;
13956 
13957  assert(var != NULL);
13958  assert(stat != NULL);
13959 
13960  switch( SCIPvarGetStatus(var) )
13961  {
13963  if( var->data.original.transvar == NULL )
13964  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13965  else
13966  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13967 
13968  case SCIP_VARSTATUS_LOOSE:
13969  case SCIP_VARSTATUS_COLUMN:
13970  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13971 
13972  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13973  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13974  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13975 
13976  case SCIP_VARSTATUS_FIXED:
13977  return 0.0;
13978 
13980  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13981 
13983  return 0.0;
13984 
13986  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13987 
13988  default:
13989  SCIPerrorMessage("unknown variable status\n");
13990  SCIPABORT();
13991  return 0.0; /*lint !e527*/
13992  }
13993 }
13994 
13995 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13996  * only using the pseudo cost information of the current run
13997  */
13999  SCIP_VAR* var, /**< problem variable */
14000  SCIP_STAT* stat, /**< problem statistics */
14001  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14002  )
14003 {
14004  SCIP_BRANCHDIR dir;
14005 
14006  assert(var != NULL);
14007  assert(stat != NULL);
14008 
14009  switch( SCIPvarGetStatus(var) )
14010  {
14012  if( var->data.original.transvar == NULL )
14013  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14014  else
14015  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14016 
14017  case SCIP_VARSTATUS_LOOSE:
14018  case SCIP_VARSTATUS_COLUMN:
14019  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14020 
14021  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14022  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14023  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14024 
14025  case SCIP_VARSTATUS_FIXED:
14026  return 0.0;
14027 
14029  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14030 
14032  return 0.0;
14033 
14035  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14036 
14037  default:
14038  SCIPerrorMessage("unknown variable status\n");
14039  SCIPABORT();
14040  return 0.0; /*lint !e527*/
14041  }
14042 }
14043 
14044 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14046  SCIP_VAR* var, /**< problem variable */
14047  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14048  )
14049 {
14050  assert(var != NULL);
14051  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14052 
14053  switch( SCIPvarGetStatus(var) )
14054  {
14056  if( var->data.original.transvar == NULL )
14057  return 0.0;
14058  else
14059  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14060 
14061  case SCIP_VARSTATUS_LOOSE:
14062  case SCIP_VARSTATUS_COLUMN:
14063  return SCIPhistoryGetPseudocostCount(var->history, dir);
14064 
14065  case SCIP_VARSTATUS_FIXED:
14066  return 0.0;
14067 
14069  if( var->data.aggregate.scalar > 0.0 )
14070  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14071  else
14073 
14075  return 0.0;
14076 
14079 
14080  default:
14081  SCIPerrorMessage("unknown variable status\n");
14082  SCIPABORT();
14083  return 0.0; /*lint !e527*/
14084  }
14085 }
14086 
14087 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14088  * only using the pseudo cost information of the current run
14089  */
14091  SCIP_VAR* var, /**< problem variable */
14092  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14093  )
14094 {
14095  assert(var != NULL);
14096  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14097 
14098  switch( SCIPvarGetStatus(var) )
14099  {
14101  if( var->data.original.transvar == NULL )
14102  return 0.0;
14103  else
14105 
14106  case SCIP_VARSTATUS_LOOSE:
14107  case SCIP_VARSTATUS_COLUMN:
14108  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14109 
14110  case SCIP_VARSTATUS_FIXED:
14111  return 0.0;
14112 
14114  if( var->data.aggregate.scalar > 0.0 )
14116  else
14118 
14120  return 0.0;
14121 
14124 
14125  default:
14126  SCIPerrorMessage("unknown variable status\n");
14127  SCIPABORT();
14128  return 0.0; /*lint !e527*/
14129  }
14130 }
14131 
14132 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14134  SCIP_VAR* var, /**< problem variable */
14135  SCIP_STAT* stat, /**< problem statistics */
14136  SCIP_SET* set, /**< global SCIP settings */
14137  SCIP_Real solval /**< solution value, e.g., LP solution value */
14138  )
14139 {
14140  SCIP_Real upscore;
14141  SCIP_Real downscore;
14142  SCIP_Real solvaldeltaup;
14143  SCIP_Real solvaldeltadown;
14144 
14145  /* LP root estimate only works for variables with fractional LP root solution */
14146  if( SCIPsetIsFeasIntegral(set, solval) )
14147  return 0.0;
14148 
14149  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14151  return 0.0;
14152 
14153  /* compute delta's to ceil and floor of root LP solution value */
14154  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14155  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14156 
14157  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14158  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14159 
14160  return MIN(upscore, downscore);
14161 }
14162 
14163 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14165  SCIP_VAR* var, /**< problem variable */
14166  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14167  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14168  )
14169 {
14170  assert(var != NULL);
14171  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14172 
14173  switch( SCIPvarGetStatus(var) )
14174  {
14176  if( var->data.original.transvar == NULL )
14177  return 0.0;
14178  else
14179  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14180 
14181  case SCIP_VARSTATUS_LOOSE:
14182  case SCIP_VARSTATUS_COLUMN:
14183  if( onlycurrentrun )
14185  else
14186  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14187 
14188  case SCIP_VARSTATUS_FIXED:
14189  return 0.0;
14190 
14192  if( var->data.aggregate.scalar > 0.0 )
14193  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14194  else
14195  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14196 
14198  return 0.0;
14199 
14201  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14202 
14203  default:
14204  SCIPerrorMessage("unknown variable status\n");
14205  SCIPABORT();
14206  return 0.0; /*lint !e527*/
14207  }
14208 }
14209 
14210 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14211  *
14212  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14213  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14214  * of 2 * clevel - 1.
14215  *
14216  * @return value of confidence bound for this variable
14217  */
14219  SCIP_VAR* var, /**< variable in question */
14220  SCIP_SET* set, /**< global SCIP settings */
14221  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14222  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14223  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14224  )
14225 {
14226  SCIP_Real confidencebound;
14227 
14228  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14229  if( SCIPsetIsFeasPositive(set, confidencebound) )
14230  {
14231  SCIP_Real count;
14232 
14233  if( onlycurrentrun )
14234  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14235  else
14236  count = SCIPvarGetPseudocostCount(var, dir);
14237  /* assertion is valid because variance is positive */
14238  assert(count >= 1.9);
14239 
14240  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14241  confidencebound = sqrt(confidencebound);
14242 
14243  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14244  * the number of pseudo cost evaluations of this variable in the respective direction. */
14245  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14246  }
14247  else
14248  confidencebound = 0.0;
14249 
14250  return confidencebound;
14251 }
14252 
14253 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14254  * Error is calculated at a specific confidence level
14255  */
14257  SCIP_VAR* var, /**< variable in question */
14258  SCIP_SET* set, /**< global SCIP settings */
14259  SCIP_STAT* stat, /**< problem statistics */
14260  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14261  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14262  )
14263 {
14264  SCIP_Real downsize;
14265  SCIP_Real upsize;
14266  SCIP_Real size;
14267  SCIP_Real relerrorup;
14268  SCIP_Real relerrordown;
14269  SCIP_Real relerror;
14270 
14271  /* check, if the pseudo cost score of the variable is reliable */
14274  size = MIN(downsize, upsize);
14275 
14276  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14277  if( size <= 1.9 )
14278  return FALSE;
14279 
14280  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14281  * confidence interval bound at confidence level of 95% for individual variable reliability.
14282  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14283  */
14284  if( downsize >= 1.9 )
14285  {
14286  SCIP_Real normval;
14287 
14288  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14289  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14290  normval = MAX(1.0, normval);
14291 
14292  relerrordown /= normval;
14293  }
14294  else
14295  relerrordown = 0.0;
14296 
14297  if( upsize >= 1.9 )
14298  {
14299  SCIP_Real normval;
14300 
14301  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14302  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14303  normval = MAX(1.0, normval);
14304  relerrorup /= normval;
14305  }
14306  else
14307  relerrorup = 0.0;
14308 
14309  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14310  relerror = MAX(relerrorup, relerrordown);
14311 
14312  return (relerror <= threshold);
14313 }
14314 
14315 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14316  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14317  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14318  * unknown location means of the underlying pseudo-cost distributions of x and y.
14319  *
14320  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14321  * better than x (despite the current information), meaning that y can be expected to yield branching
14322  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14323  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14324  * than y.
14325  *
14326  * @note The order of x and y matters for the one-sided hypothesis
14327  *
14328  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14329  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14330  *
14331  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14332  */
14334  SCIP_SET* set, /**< global SCIP settings */
14335  SCIP_STAT* stat, /**< problem statistics */
14336  SCIP_VAR* varx, /**< variable x */
14337  SCIP_Real fracx, /**< the fractionality of variable x */
14338  SCIP_VAR* vary, /**< variable y */
14339  SCIP_Real fracy, /**< the fractionality of variable y */
14340  SCIP_BRANCHDIR dir, /**< branching direction */
14341  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14342  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14343  )
14344 {
14345  SCIP_Real meanx;
14346  SCIP_Real meany;
14347  SCIP_Real variancex;
14348  SCIP_Real variancey;
14349  SCIP_Real countx;
14350  SCIP_Real county;
14351  SCIP_Real tresult;
14352  SCIP_Real realdirection;
14353 
14354  if( varx == vary )
14355  return FALSE;
14356 
14357  countx = SCIPvarGetPseudocostCount(varx, dir);
14358  county = SCIPvarGetPseudocostCount(vary, dir);
14359 
14360  /* if not at least 2 measurements were taken, return FALSE */
14361  if( countx <= 1.9 || county <= 1.9 )
14362  return FALSE;
14363 
14364  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14365 
14366  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14367  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14368 
14369  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14370  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14371 
14372  /* if there is no variance, the means are taken from a constant distribution */
14373  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14374  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14375 
14376  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14377 
14378  /* for the two-sided hypothesis, just take the absolute of t */
14379  if( !onesided )
14380  tresult = REALABS(tresult);
14381 
14382  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14383 }
14384 
14385 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14386  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14387  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14388  * of at least \p threshold.
14389  *
14390  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14391  * the estimated probability to exceed \p threshold is less than 25 %.
14392  *
14393  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14394  * of confidence.
14395  *
14396  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14397  * at the given confidence level \p clevel.
14398  */
14400  SCIP_SET* set, /**< global SCIP settings */
14401  SCIP_STAT* stat, /**< problem statistics */
14402  SCIP_VAR* var, /**< variable x */
14403  SCIP_Real frac, /**< the fractionality of variable x */
14404  SCIP_Real threshold, /**< the threshold to test against */
14405  SCIP_BRANCHDIR dir, /**< branching direction */
14406  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14407  )
14408 {
14409  SCIP_Real mean;
14410  SCIP_Real variance;
14411  SCIP_Real count;
14412  SCIP_Real realdirection;
14413  SCIP_Real probability;
14414  SCIP_Real problimit;
14415 
14416  count = SCIPvarGetPseudocostCount(var, dir);
14417 
14418  /* if not at least 2 measurements were taken, return FALSE */
14419  if( count <= 1.9 )
14420  return FALSE;
14421 
14422  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14423 
14424  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14425  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14426 
14427  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14428  if( SCIPsetIsFeasGE(set, mean, threshold) )
14429  return FALSE;
14430 
14431  /* if there is no variance, the means are taken from a constant distribution */
14432  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14433  return SCIPsetIsFeasLT(set, mean, threshold);
14434 
14435  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14436  probability = SCIPnormalCDF(mean, variance, threshold);
14437 
14438  /* determine a probability limit corresponding to the given confidence level */
14439  switch( clevel )
14440  {
14442  problimit = 0.75;
14443  break;
14445  problimit = 0.875;
14446  break;
14448  problimit = 0.9;
14449  break;
14451  problimit = 0.95;
14452  break;
14454  problimit = 0.975;
14455  break;
14456  default:
14457  problimit = -1;
14458  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14459  SCIPABORT();
14460  break;
14461  }
14462 
14463  return (probability >= problimit);
14464 }
14465 
14466 /** find the corresponding history entry if already existing, otherwise create new entry */
14467 static
14469  SCIP_VAR* var, /**< problem variable */
14470  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14471  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14472  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14473  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14474  )
14475 {
14476  assert(var != NULL);
14477  assert(blkmem != NULL);
14478  assert(set != NULL);
14479  assert(history != NULL);
14480 
14481  (*history) = NULL;
14482 
14483  if( var->valuehistory == NULL )
14484  {
14485  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14486  }
14487 
14488  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14489 
14490  return SCIP_OKAY;
14491 }
14492 
14493 /** check if value based history should be used */
14494 static
14496  SCIP_VAR* var, /**< problem variable */
14497  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14498  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14499  )
14500 {
14501  /* check if the domain value is unknown (not specific) */
14502  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14503  return FALSE;
14504 
14505  assert(set != NULL);
14506 
14507  /* check if value based history should be collected */
14508  if( !set->history_valuebased )
14509  return FALSE;
14510 
14511  /* value based history is not collected for binary variable since the standard history already contains all information */
14512  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14513  return FALSE;
14514 
14515  /* value based history is not collected for continuous variables */
14517  return FALSE;
14518 
14519  return TRUE;
14520 }
14521 
14522 /** increases VSIDS of the variable by the given weight */
14524  SCIP_VAR* var, /**< problem variable */
14525  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14526  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14527  SCIP_STAT* stat, /**< problem statistics */
14528  SCIP_BRANCHDIR dir, /**< branching direction */
14529  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14530  SCIP_Real weight /**< weight of this update in VSIDS */
14531  )
14532 {
14533  assert(var != NULL);
14534  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14535 
14536  /* check if history statistics should be collected for a variable */
14537  if( !stat->collectvarhistory )
14538  return SCIP_OKAY;
14539 
14540  if( SCIPsetIsZero(set, weight) )
14541  return SCIP_OKAY;
14542 
14543  switch( SCIPvarGetStatus(var) )
14544  {
14546  if( var->data.original.transvar == NULL )
14547  {
14548  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14549  return SCIP_INVALIDDATA;
14550  }
14551  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14552  return SCIP_OKAY;
14553 
14554  case SCIP_VARSTATUS_LOOSE:
14555  case SCIP_VARSTATUS_COLUMN:
14556  {
14557  SCIPhistoryIncVSIDS(var->history, dir, weight);
14558  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14559 
14560  if( useValuehistory(var, value, set) )
14561  {
14562  SCIP_HISTORY* history;
14563 
14564  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14565  assert(history != NULL);
14566 
14567  SCIPhistoryIncVSIDS(history, dir, weight);
14568  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14569  value, weight, SCIPhistoryGetVSIDS(history, dir));
14570  }
14571 
14572  return SCIP_OKAY;
14573  }
14574  case SCIP_VARSTATUS_FIXED:
14575  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14576  return SCIP_INVALIDDATA;
14577 
14579  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14580 
14581  if( var->data.aggregate.scalar > 0.0 )
14582  {
14583  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14584  }
14585  else
14586  {
14587  assert(var->data.aggregate.scalar < 0.0);
14588  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14589  }
14590  return SCIP_OKAY;
14591 
14593  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14594  return SCIP_INVALIDDATA;
14595 
14597  value = 1.0 - value;
14598 
14599  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14600  return SCIP_OKAY;
14601 
14602  default:
14603  SCIPerrorMessage("unknown variable status\n");
14604  return SCIP_INVALIDDATA;
14605  }
14606 }
14607 
14608 /** scales the VSIDS of the variable by the given scalar */
14610  SCIP_VAR* var, /**< problem variable */
14611  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14612  )
14613 {
14614  assert(var != NULL);
14615 
14616  switch( SCIPvarGetStatus(var) )
14617  {
14619  if( var->data.original.transvar == NULL )
14620  {
14621  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14622  return SCIP_INVALIDDATA;
14623  }
14625  return SCIP_OKAY;
14626 
14627  case SCIP_VARSTATUS_LOOSE:
14628  case SCIP_VARSTATUS_COLUMN:
14629  {
14630  SCIPhistoryScaleVSIDS(var->history, scalar);
14631  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14633 
14634  return SCIP_OKAY;
14635  }
14636  case SCIP_VARSTATUS_FIXED:
14637  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14638  return SCIP_INVALIDDATA;
14639 
14641  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14642  return SCIP_OKAY;
14643 
14645  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14646  return SCIP_INVALIDDATA;
14647 
14649  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14650  return SCIP_OKAY;
14651 
14652  default:
14653  SCIPerrorMessage("unknown variable status\n");
14654  return SCIP_INVALIDDATA;
14655  }
14656 }
14657 
14658 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14660  SCIP_VAR* var, /**< problem variable */
14661  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14662  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14663  SCIP_STAT* stat, /**< problem statistics */
14664  SCIP_BRANCHDIR dir, /**< branching direction */
14665  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14666  SCIP_Real length /**< length of the conflict */
14667  )
14668 {
14669  assert(var != NULL);
14670  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14671 
14672  /* check if history statistics should be collected for a variable */
14673  if( !stat->collectvarhistory )
14674  return SCIP_OKAY;
14675 
14676  switch( SCIPvarGetStatus(var) )
14677  {
14679  if( var->data.original.transvar == NULL )
14680  {
14681  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14682  return SCIP_INVALIDDATA;
14683  }
14684  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14685  return SCIP_OKAY;
14686 
14687  case SCIP_VARSTATUS_LOOSE:
14688  case SCIP_VARSTATUS_COLUMN:
14689  {
14690  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14691  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14692 
14693  if( useValuehistory(var, value, set) )
14694  {
14695  SCIP_HISTORY* history;
14696 
14697  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14698  assert(history != NULL);
14699 
14700  SCIPhistoryIncNActiveConflicts(history, dir, length);
14701  }
14702 
14703  return SCIP_OKAY;
14704  }
14705  case SCIP_VARSTATUS_FIXED:
14706  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14707  return SCIP_INVALIDDATA;
14708 
14710  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14711 
14712  if( var->data.aggregate.scalar > 0.0 )
14713  {
14714  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14715  }
14716  else
14717  {
14718  assert(var->data.aggregate.scalar < 0.0);
14719  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14720  }
14721  return SCIP_OKAY;
14722 
14724  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14725  return SCIP_INVALIDDATA;
14726 
14728  value = 1.0 - value;
14729 
14730  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14731  return SCIP_OKAY;
14732 
14733  default:
14734  SCIPerrorMessage("unknown variable status\n");
14735  return SCIP_INVALIDDATA;
14736  }
14737 }
14738 
14739 /** gets the number of active conflicts containing this variable in given direction */
14741  SCIP_VAR* var, /**< problem variable */
14742  SCIP_STAT* stat, /**< problem statistics */
14743  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14744  )
14745 {
14746  assert(var != NULL);
14747  assert(stat != NULL);
14748  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14749 
14750  switch( SCIPvarGetStatus(var) )
14751  {
14753  if( var->data.original.transvar == NULL )
14754  return 0;
14755  else
14756  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14757 
14758  case SCIP_VARSTATUS_LOOSE:
14759  case SCIP_VARSTATUS_COLUMN:
14760  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14761 
14762  case SCIP_VARSTATUS_FIXED:
14763  return 0;
14764 
14766  if( var->data.aggregate.scalar > 0.0 )
14767  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14768  else
14770 
14772  return 0;
14773 
14776 
14777  default:
14778  SCIPerrorMessage("unknown variable status\n");
14779  SCIPABORT();
14780  return 0; /*lint !e527*/
14781  }
14782 }
14783 
14784 /** gets the number of active conflicts containing this variable in given direction
14785  * in the current run
14786  */
14788  SCIP_VAR* var, /**< problem variable */
14789  SCIP_STAT* stat, /**< problem statistics */
14790  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14791  )
14792 {
14793  assert(var != NULL);
14794  assert(stat != NULL);
14795  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14796 
14797  switch( SCIPvarGetStatus(var) )
14798  {
14800  if( var->data.original.transvar == NULL )
14801  return 0;
14802  else
14804 
14805  case SCIP_VARSTATUS_LOOSE:
14806  case SCIP_VARSTATUS_COLUMN:
14807  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14808 
14809  case SCIP_VARSTATUS_FIXED:
14810  return 0;
14811 
14813  if( var->data.aggregate.scalar > 0.0 )
14814  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14815  else
14817 
14819  return 0;
14820 
14823 
14824  default:
14825  SCIPerrorMessage("unknown variable status\n");
14826  SCIPABORT();
14827  return 0; /*lint !e527*/
14828  }
14829 }
14830 
14831 /** gets the average conflict length in given direction due to branching on the variable */
14833  SCIP_VAR* var, /**< problem variable */
14834  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14835  )
14836 {
14837  assert(var != NULL);
14838  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14839 
14840  switch( SCIPvarGetStatus(var) )
14841  {
14843  if( var->data.original.transvar == NULL )
14844  return 0.0;
14845  else
14847 
14848  case SCIP_VARSTATUS_LOOSE:
14849  case SCIP_VARSTATUS_COLUMN:
14850  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14851  case SCIP_VARSTATUS_FIXED:
14852  return 0.0;
14853 
14855  if( var->data.aggregate.scalar > 0.0 )
14856  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14857  else
14859 
14861  return 0.0;
14862 
14865 
14866  default:
14867  SCIPerrorMessage("unknown variable status\n");
14868  SCIPABORT();
14869  return 0.0; /*lint !e527*/
14870  }
14871 }
14872 
14873 /** gets the average conflict length in given direction due to branching on the variable
14874  * in the current run
14875  */
14877  SCIP_VAR* var, /**< problem variable */
14878  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14879  )
14880 {
14881  assert(var != NULL);
14882  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14883 
14884  switch( SCIPvarGetStatus(var) )
14885  {
14887  if( var->data.original.transvar == NULL )
14888  return 0.0;
14889  else
14891 
14892  case SCIP_VARSTATUS_LOOSE:
14893  case SCIP_VARSTATUS_COLUMN:
14894  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14895 
14896  case SCIP_VARSTATUS_FIXED:
14897  return 0.0;
14898 
14900  if( var->data.aggregate.scalar > 0.0 )
14902  else
14904 
14906  return 0.0;
14907 
14910 
14911  default:
14912  SCIPerrorMessage("unknown variable status\n");
14913  SCIPABORT();
14914  return 0.0; /*lint !e527*/
14915  }
14916 }
14917 
14918 /** increases the number of branchings counter of the variable */
14920  SCIP_VAR* var, /**< problem variable */
14921  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14922  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14923  SCIP_STAT* stat, /**< problem statistics */
14924  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14925  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14926  int depth /**< depth at which the bound change took place */
14927  )
14928 {
14929  assert(var != NULL);
14930  assert(stat != NULL);
14931  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14932 
14933  /* check if history statistics should be collected for a variable */
14934  if( !stat->collectvarhistory )
14935  return SCIP_OKAY;
14936 
14937  switch( SCIPvarGetStatus(var) )
14938  {
14940  if( var->data.original.transvar == NULL )
14941  {
14942  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14943  return SCIP_INVALIDDATA;
14944  }
14945  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14946  return SCIP_OKAY;
14947 
14948  case SCIP_VARSTATUS_LOOSE:
14949  case SCIP_VARSTATUS_COLUMN:
14950  {
14951  SCIPhistoryIncNBranchings(var->history, dir, depth);
14952  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14953  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14954  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14955 
14956  if( useValuehistory(var, value, set) )
14957  {
14958  SCIP_HISTORY* history;
14959 
14960  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14961  assert(history != NULL);
14962 
14963  SCIPhistoryIncNBranchings(history, dir, depth);
14964  }
14965 
14966  return SCIP_OKAY;
14967  }
14968  case SCIP_VARSTATUS_FIXED:
14969  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14970  return SCIP_INVALIDDATA;
14971 
14973  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14974 
14975  if( var->data.aggregate.scalar > 0.0 )
14976  {
14977  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14978  }
14979  else
14980  {
14981  assert(var->data.aggregate.scalar < 0.0);
14982  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14983  }
14984  return SCIP_OKAY;
14985 
14987  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14988  return SCIP_INVALIDDATA;
14989 
14991  value = 1.0 - value;
14992 
14993  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14994  return SCIP_OKAY;
14995 
14996  default:
14997  SCIPerrorMessage("unknown variable status\n");
14998  return SCIP_INVALIDDATA;
14999  }
15000 }
15001 
15002 /** increases the inference sum of the variable by the given weight */
15004  SCIP_VAR* var, /**< problem variable */
15005  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15006  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15007  SCIP_STAT* stat, /**< problem statistics */
15008  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15009  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15010  SCIP_Real weight /**< weight of this update in inference score */
15011  )
15012 {
15013  assert(var != NULL);
15014  assert(stat != NULL);
15015  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15016 
15017  /* check if history statistics should be collected for a variable */
15018  if( !stat->collectvarhistory )
15019  return SCIP_OKAY;
15020 
15021  switch( SCIPvarGetStatus(var) )
15022  {
15024  if( var->data.original.transvar == NULL )
15025  {
15026  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15027  return SCIP_INVALIDDATA;
15028  }
15029  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15030  return SCIP_OKAY;
15031 
15032  case SCIP_VARSTATUS_LOOSE:
15033  case SCIP_VARSTATUS_COLUMN:
15034  {
15035  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15036  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15037  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15038  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15039 
15040  if( useValuehistory(var, value, set) )
15041  {
15042  SCIP_HISTORY* history;
15043 
15044  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15045  assert(history != NULL);
15046 
15047  SCIPhistoryIncInferenceSum(history, dir, weight);
15048  }
15049 
15050  return SCIP_OKAY;
15051  }
15052  case SCIP_VARSTATUS_FIXED:
15053  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15054  return SCIP_INVALIDDATA;
15055 
15057  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15058 
15059  if( var->data.aggregate.scalar > 0.0 )
15060  {
15061  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15062  }
15063  else
15064  {
15065  assert(var->data.aggregate.scalar < 0.0);
15066  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15067  }
15068  return SCIP_OKAY;
15069 
15071  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15072  return SCIP_INVALIDDATA;
15073 
15075  value = 1.0 - value;
15076 
15077  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15078  return SCIP_OKAY;
15079 
15080  default:
15081  SCIPerrorMessage("unknown variable status\n");
15082  return SCIP_INVALIDDATA;
15083  }
15084 }
15085 
15086 /** increases the cutoff sum of the variable by the given weight */
15088  SCIP_VAR* var, /**< problem variable */
15089  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15090  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15091  SCIP_STAT* stat, /**< problem statistics */
15092  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15093  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15094  SCIP_Real weight /**< weight of this update in cutoff score */
15095  )
15096 {
15097  assert(var != NULL);
15098  assert(stat != NULL);
15099  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15100 
15101  /* check if history statistics should be collected for a variable */
15102  if( !stat->collectvarhistory )
15103  return SCIP_OKAY;
15104 
15105  switch( SCIPvarGetStatus(var) )
15106  {
15108  if( var->data.original.transvar == NULL )
15109  {
15110  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15111  return SCIP_INVALIDDATA;
15112  }
15113  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15114  return SCIP_OKAY;
15115 
15116  case SCIP_VARSTATUS_LOOSE:
15117  case SCIP_VARSTATUS_COLUMN:
15118  {
15119  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15120  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15121  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15122  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15123 
15124  if( useValuehistory(var, value, set) )
15125  {
15126  SCIP_HISTORY* history;
15127 
15128  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15129  assert(history != NULL);
15130 
15131  SCIPhistoryIncCutoffSum(history, dir, weight);
15132  }
15133 
15134  return SCIP_OKAY;
15135  }
15136  case SCIP_VARSTATUS_FIXED:
15137  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15138  return SCIP_INVALIDDATA;
15139 
15141  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15142 
15143  if( var->data.aggregate.scalar > 0.0 )
15144  {
15145  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15146  }
15147  else
15148  {
15149  assert(var->data.aggregate.scalar < 0.0);
15150  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15151  }
15152  return SCIP_OKAY;
15153 
15155  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15156  return SCIP_INVALIDDATA;
15157 
15159  value = 1.0 - value;
15160 
15161  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15162  return SCIP_OKAY;
15163 
15164  default:
15165  SCIPerrorMessage("unknown variable status\n");
15166  return SCIP_INVALIDDATA;
15167  }
15168 }
15169 
15170 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15172  SCIP_VAR* var, /**< problem variable */
15173  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15174  )
15175 {
15176  assert(var != NULL);
15177  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15178 
15179  switch( SCIPvarGetStatus(var) )
15180  {
15182  if( var->data.original.transvar == NULL )
15183  return 0;
15184  else
15185  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15186 
15187  case SCIP_VARSTATUS_LOOSE:
15188  case SCIP_VARSTATUS_COLUMN:
15189  return SCIPhistoryGetNBranchings(var->history, dir);
15190 
15191  case SCIP_VARSTATUS_FIXED:
15192  return 0;
15193 
15195  if( var->data.aggregate.scalar > 0.0 )
15196  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15197  else
15199 
15201  return 0;
15202 
15205 
15206  default:
15207  SCIPerrorMessage("unknown variable status\n");
15208  SCIPABORT();
15209  return 0; /*lint !e527*/
15210  }
15211 }
15212 
15213 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15214  * in the current run
15215  */
15217  SCIP_VAR* var, /**< problem variable */
15218  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15219  )
15220 {
15221  assert(var != NULL);
15222  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15223 
15224  switch( SCIPvarGetStatus(var) )
15225  {
15227  if( var->data.original.transvar == NULL )
15228  return 0;
15229  else
15231 
15232  case SCIP_VARSTATUS_LOOSE:
15233  case SCIP_VARSTATUS_COLUMN:
15234  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15235 
15236  case SCIP_VARSTATUS_FIXED:
15237  return 0;
15238 
15240  if( var->data.aggregate.scalar > 0.0 )
15242  else
15244 
15246  return 0;
15247 
15250 
15251  default:
15252  SCIPerrorMessage("unknown variable status\n");
15253  SCIPABORT();
15254  return 0; /*lint !e527*/
15255  }
15256 }
15257 
15258 /** returns the average depth of bound changes in given direction due to branching on the variable */
15260  SCIP_VAR* var, /**< problem variable */
15261  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15262  )
15263 {
15264  assert(var != NULL);
15265  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15266 
15267  switch( SCIPvarGetStatus(var) )
15268  {
15270  if( var->data.original.transvar == NULL )
15271  return 0.0;
15272  else
15273  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15274 
15275  case SCIP_VARSTATUS_LOOSE:
15276  case SCIP_VARSTATUS_COLUMN:
15277  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15278 
15279  case SCIP_VARSTATUS_FIXED:
15280  return 0.0;
15281 
15283  if( var->data.aggregate.scalar > 0.0 )
15284  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15285  else
15287 
15289  return 0.0;
15290 
15293 
15294  default:
15295  SCIPerrorMessage("unknown variable status\n");
15296  SCIPABORT();
15297  return 0.0; /*lint !e527*/
15298  }
15299 }
15300 
15301 /** returns the average depth of bound changes in given direction due to branching on the variable
15302  * in the current run
15303  */
15305  SCIP_VAR* var, /**< problem variable */
15306  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15307  )
15308 {
15309  assert(var != NULL);
15310  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15311 
15312  switch( SCIPvarGetStatus(var) )
15313  {
15315  if( var->data.original.transvar == NULL )
15316  return 0.0;
15317  else
15319 
15320  case SCIP_VARSTATUS_LOOSE:
15321  case SCIP_VARSTATUS_COLUMN:
15322  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15323 
15324  case SCIP_VARSTATUS_FIXED:
15325  return 0.0;
15326 
15328  if( var->data.aggregate.scalar > 0.0 )
15330  else
15333 
15335  return 0.0;
15336 
15339  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15340 
15341  default:
15342  SCIPerrorMessage("unknown variable status\n");
15343  SCIPABORT();
15344  return 0.0; /*lint !e527*/
15345  }
15346 }
15347 
15348 /** returns the variable's VSIDS score */
15350  SCIP_VAR* var, /**< problem variable */
15351  SCIP_STAT* stat, /**< problem statistics */
15352  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15353  )
15354 {
15355  assert(var != NULL);
15356  assert(stat != NULL);
15357  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15358 
15360  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15361 
15362  switch( SCIPvarGetStatus(var) )
15363  {
15365  if( var->data.original.transvar == NULL )
15366  return 0.0;
15367  else
15368  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15369 
15370  case SCIP_VARSTATUS_LOOSE:
15371  case SCIP_VARSTATUS_COLUMN:
15372  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15373  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15374 
15375  case SCIP_VARSTATUS_FIXED:
15376  return 0.0;
15377 
15379  if( var->data.aggregate.scalar > 0.0 )
15380  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15381  else
15382  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15383 
15385  return 0.0;
15386 
15388  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15389 
15390  default:
15391  SCIPerrorMessage("unknown variable status\n");
15392  SCIPABORT();
15393  return 0.0; /*lint !e527*/
15394  }
15395 }
15396 
15397 /** returns the variable's VSIDS score only using conflicts of the current run */
15399  SCIP_VAR* var, /**< problem variable */
15400  SCIP_STAT* stat, /**< problem statistics */
15401  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15402  )
15403 {
15404  assert(var != NULL);
15405  assert(stat != NULL);
15406  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15407 
15408  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15409  {
15410  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15411  return SCIP_INVALID;
15412  }
15413 
15414  switch( SCIPvarGetStatus(var) )
15415  {
15417  if( var->data.original.transvar == NULL )
15418  return 0.0;
15419  else
15420  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15421 
15422  case SCIP_VARSTATUS_LOOSE:
15423  case SCIP_VARSTATUS_COLUMN:
15424  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15425 
15426  case SCIP_VARSTATUS_FIXED:
15427  return 0.0;
15428 
15430  if( var->data.aggregate.scalar > 0.0 )
15431  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15432  else
15434 
15436  return 0.0;
15437 
15440 
15441  default:
15442  SCIPerrorMessage("unknown variable status\n");
15443  SCIPABORT();
15444  return 0.0; /*lint !e527*/
15445  }
15446 }
15447 
15448 /** returns the number of inferences branching on this variable in given direction triggered */
15450  SCIP_VAR* var, /**< problem variable */
15451  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15452  )
15453 {
15454  assert(var != NULL);
15455  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15456 
15457  switch( SCIPvarGetStatus(var) )
15458  {
15460  if( var->data.original.transvar == NULL )
15461  return 0.0;
15462  else
15463  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15464 
15465  case SCIP_VARSTATUS_LOOSE:
15466  case SCIP_VARSTATUS_COLUMN:
15467  return SCIPhistoryGetInferenceSum(var->history, dir);
15468 
15469  case SCIP_VARSTATUS_FIXED:
15470  return 0.0;
15471 
15473  if( var->data.aggregate.scalar > 0.0 )
15474  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15475  else
15477 
15479  return 0.0;
15480 
15483 
15484  default:
15485  SCIPerrorMessage("unknown variable status\n");
15486  SCIPABORT();
15487  return 0.0; /*lint !e527*/
15488  }
15489 }
15490 
15491 /** returns the number of inferences branching on this variable in given direction triggered
15492  * in the current run
15493  */
15495  SCIP_VAR* var, /**< problem variable */
15496  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15497  )
15498 {
15499  assert(var != NULL);
15500  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15501 
15502  switch( SCIPvarGetStatus(var) )
15503  {
15505  if( var->data.original.transvar == NULL )
15506  return 0.0;
15507  else
15509 
15510  case SCIP_VARSTATUS_LOOSE:
15511  case SCIP_VARSTATUS_COLUMN:
15512  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15513 
15514  case SCIP_VARSTATUS_FIXED:
15515  return 0.0;
15516 
15518  if( var->data.aggregate.scalar > 0.0 )
15520  else
15522 
15524  return 0.0;
15525 
15528 
15529  default:
15530  SCIPerrorMessage("unknown variable status\n");
15531  SCIPABORT();
15532  return 0.0; /*lint !e527*/
15533  }
15534 }
15535 
15536 /** returns the average number of inferences found after branching on the variable in given direction */
15538  SCIP_VAR* var, /**< problem variable */
15539  SCIP_STAT* stat, /**< problem statistics */
15540  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15541  )
15542 {
15543  assert(var != NULL);
15544  assert(stat != NULL);
15545  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15546 
15547  switch( SCIPvarGetStatus(var) )
15548  {
15550  if( var->data.original.transvar == NULL )
15551  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15552  else
15553  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15554 
15555  case SCIP_VARSTATUS_LOOSE:
15556  case SCIP_VARSTATUS_COLUMN:
15557  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15558  return SCIPhistoryGetAvgInferences(var->history, dir);
15559  else
15560  {
15561  int nimpls;
15562  int ncliques;
15563 
15564  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15565  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15566  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15567  }
15568 
15569  case SCIP_VARSTATUS_FIXED:
15570  return 0.0;
15571 
15573  if( var->data.aggregate.scalar > 0.0 )
15574  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15575  else
15577 
15579  return 0.0;
15580 
15582  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15583 
15584  default:
15585  SCIPerrorMessage("unknown variable status\n");
15586  SCIPABORT();
15587  return 0.0; /*lint !e527*/
15588  }
15589 }
15590 
15591 /** returns the average number of inferences found after branching on the variable in given direction
15592  * in the current run
15593  */
15595  SCIP_VAR* var, /**< problem variable */
15596  SCIP_STAT* stat, /**< problem statistics */
15597  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15598  )
15599 {
15600  assert(var != NULL);
15601  assert(stat != NULL);
15602  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15603 
15604  switch( SCIPvarGetStatus(var) )
15605  {
15607  if( var->data.original.transvar == NULL )
15608  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15609  else
15610  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15611 
15612  case SCIP_VARSTATUS_LOOSE:
15613  case SCIP_VARSTATUS_COLUMN:
15614  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15615  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15616  else
15617  {
15618  int nimpls;
15619  int ncliques;
15620 
15621  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15622  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15623  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15624  }
15625 
15626  case SCIP_VARSTATUS_FIXED:
15627  return 0.0;
15628 
15630  if( var->data.aggregate.scalar > 0.0 )
15631  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15632  else
15634 
15636  return 0.0;
15637 
15640 
15641  default:
15642  SCIPerrorMessage("unknown variable status\n");
15643  SCIPABORT();
15644  return 0.0; /*lint !e527*/
15645  }
15646 }
15647 
15648 /** returns the number of cutoffs branching on this variable in given direction produced */
15650  SCIP_VAR* var, /**< problem variable */
15651  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15652  )
15653 {
15654  assert(var != NULL);
15655  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15656 
15657  switch( SCIPvarGetStatus(var) )
15658  {
15660  if( var->data.original.transvar == NULL )
15661  return 0;
15662  else
15663  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15664 
15665  case SCIP_VARSTATUS_LOOSE:
15666  case SCIP_VARSTATUS_COLUMN:
15667  return SCIPhistoryGetCutoffSum(var->history, dir);
15668 
15669  case SCIP_VARSTATUS_FIXED:
15670  return 0;
15671 
15673  if( var->data.aggregate.scalar > 0.0 )
15674  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15675  else
15677 
15679  return 0;
15680 
15683 
15684  default:
15685  SCIPerrorMessage("unknown variable status\n");
15686  SCIPABORT();
15687  return 0; /*lint !e527*/
15688  }
15689 }
15690 
15691 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15693  SCIP_VAR* var, /**< problem variable */
15694  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15695  )
15696 {
15697  assert(var != NULL);
15698  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15699 
15700  switch( SCIPvarGetStatus(var) )
15701  {
15703  if( var->data.original.transvar == NULL )
15704  return 0;
15705  else
15707 
15708  case SCIP_VARSTATUS_LOOSE:
15709  case SCIP_VARSTATUS_COLUMN:
15710  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15711 
15712  case SCIP_VARSTATUS_FIXED:
15713  return 0;
15714 
15716  if( var->data.aggregate.scalar > 0.0 )
15717  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15718  else
15720 
15722  return 0;
15723 
15726 
15727  default:
15728  SCIPerrorMessage("unknown variable status\n");
15729  SCIPABORT();
15730  return 0; /*lint !e527*/
15731  }
15732 }
15733 
15734 /** returns the average number of cutoffs found after branching on the variable in given direction */
15736  SCIP_VAR* var, /**< problem variable */
15737  SCIP_STAT* stat, /**< problem statistics */
15738  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15739  )
15740 {
15741  assert(var != NULL);
15742  assert(stat != NULL);
15743  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15744 
15745  switch( SCIPvarGetStatus(var) )
15746  {
15748  if( var->data.original.transvar == NULL )
15749  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15750  else
15751  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15752 
15753  case SCIP_VARSTATUS_LOOSE:
15754  case SCIP_VARSTATUS_COLUMN:
15755  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15756  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15757  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15758 
15759  case SCIP_VARSTATUS_FIXED:
15760  return 0.0;
15761 
15763  if( var->data.aggregate.scalar > 0.0 )
15764  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15765  else
15766  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15767 
15769  return 0.0;
15770 
15772  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15773 
15774  default:
15775  SCIPerrorMessage("unknown variable status\n");
15776  SCIPABORT();
15777  return 0.0; /*lint !e527*/
15778  }
15779 }
15780 
15781 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15783  SCIP_VAR* var, /**< problem variable */
15784  SCIP_STAT* stat, /**< problem statistics */
15785  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15786  )
15787 {
15788  assert(var != NULL);
15789  assert(stat != NULL);
15790  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15791 
15792  switch( SCIPvarGetStatus(var) )
15793  {
15795  if( var->data.original.transvar == NULL )
15796  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15797  else
15798  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15799 
15800  case SCIP_VARSTATUS_LOOSE:
15801  case SCIP_VARSTATUS_COLUMN:
15802  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15805 
15806  case SCIP_VARSTATUS_FIXED:
15807  return 0.0;
15808 
15810  if( var->data.aggregate.scalar > 0.0 )
15811  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15812  else
15814 
15816  return 0.0;
15817 
15820 
15821  default:
15822  SCIPerrorMessage("unknown variable status\n");
15823  SCIPABORT();
15824  return 0.0; /*lint !e527*/
15825  }
15826 }
15827 
15828 
15829 
15830 
15831 /*
15832  * information methods for bound changes
15833  */
15834 
15835 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15837  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15838  BMS_BLKMEM* blkmem, /**< block memory */
15839  SCIP_VAR* var, /**< active variable that changed the bounds */
15840  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15841  SCIP_Real oldbound, /**< old value for bound */
15842  SCIP_Real newbound /**< new value for bound */
15843  )
15844 {
15845  assert(bdchginfo != NULL);
15846 
15847  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15848  (*bdchginfo)->oldbound = oldbound;
15849  (*bdchginfo)->newbound = newbound;
15850  (*bdchginfo)->var = var;
15851  (*bdchginfo)->inferencedata.var = var;
15852  (*bdchginfo)->inferencedata.reason.prop = NULL;
15853  (*bdchginfo)->inferencedata.info = 0;
15854  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15855  (*bdchginfo)->bdchgidx.pos = -1;
15856  (*bdchginfo)->pos = 0;
15857  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15858  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15859  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15860  (*bdchginfo)->redundant = FALSE;
15861 
15862  return SCIP_OKAY;
15863 }
15864 
15865 /** frees a bound change information object */
15866 void SCIPbdchginfoFree(
15867  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15868  BMS_BLKMEM* blkmem /**< block memory */
15869  )
15870 {
15871  assert(bdchginfo != NULL);
15872 
15873  BMSfreeBlockMemory(blkmem, bdchginfo);
15874 }
15875 
15876 /** returns the bound change information for the last lower bound change on given active problem variable before or
15877  * after the bound change with the given index was applied;
15878  * returns NULL, if no change to the lower bound was applied up to this point of time
15879  */
15881  SCIP_VAR* var, /**< active problem variable */
15882  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15883  SCIP_Bool after /**< should the bound change with given index be included? */
15884  )
15885 {
15886  int i;
15887 
15888  assert(var != NULL);
15889  assert(SCIPvarIsActive(var));
15890 
15891  /* search the correct bound change information for the given bound change index */
15892  if( after )
15893  {
15894  for( i = var->nlbchginfos-1; i >= 0; --i )
15895  {
15896  assert(var->lbchginfos[i].var == var);
15898  assert(var->lbchginfos[i].pos == i);
15899 
15900  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15901  if( var->lbchginfos[i].redundant )
15902  return NULL;
15903  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15904 
15905  /* if we reached the bound change index, return the current bound change info */
15906  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15907  return &var->lbchginfos[i];
15908  }
15909  }
15910  else
15911  {
15912  for( i = var->nlbchginfos-1; i >= 0; --i )
15913  {
15914  assert(var->lbchginfos[i].var == var);
15916  assert(var->lbchginfos[i].pos == i);
15917 
15918  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15919  if( var->lbchginfos[i].redundant )
15920  return NULL;
15921  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15922 
15923  /* if we reached the bound change index, return the current bound change info */
15924  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15925  return &var->lbchginfos[i];
15926  }
15927  }
15928 
15929  return NULL;
15930 }
15931 
15932 /** returns the bound change information for the last upper bound change on given active problem variable before or
15933  * after the bound change with the given index was applied;
15934  * returns NULL, if no change to the upper bound was applied up to this point of time
15935  */
15937  SCIP_VAR* var, /**< active problem variable */
15938  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15939  SCIP_Bool after /**< should the bound change with given index be included? */
15940  )
15941 {
15942  int i;
15943 
15944  assert(var != NULL);
15945  assert(SCIPvarIsActive(var));
15946 
15947  /* search the correct bound change information for the given bound change index */
15948  if( after )
15949  {
15950  for( i = var->nubchginfos-1; i >= 0; --i )
15951  {
15952  assert(var->ubchginfos[i].var == var);
15954  assert(var->ubchginfos[i].pos == i);
15955 
15956  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15957  if( var->ubchginfos[i].redundant )
15958  return NULL;
15959  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15960 
15961  /* if we reached the bound change index, return the current bound change info */
15962  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15963  return &var->ubchginfos[i];
15964  }
15965  }
15966  else
15967  {
15968  for( i = var->nubchginfos-1; i >= 0; --i )
15969  {
15970  assert(var->ubchginfos[i].var == var);
15972  assert(var->ubchginfos[i].pos == i);
15973 
15974  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15975  if( var->ubchginfos[i].redundant )
15976  return NULL;
15977  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15978 
15979  /* if we reached the bound change index, return the current bound change info */
15980  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15981  return &var->ubchginfos[i];
15982  }
15983  }
15984 
15985  return NULL;
15986 }
15987 
15988 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15989  * before or after the bound change with the given index was applied;
15990  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15991  */
15993  SCIP_VAR* var, /**< active problem variable */
15994  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15995  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15996  SCIP_Bool after /**< should the bound change with given index be included? */
15997  )
15998 {
15999  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16000  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16001  else
16002  {
16003  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16004  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16005  }
16006 }
16007 
16008 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16009  * was applied
16010  *
16011  * @deprecated Please use SCIPgetVarLbAtIndex()
16012  */
16014  SCIP_VAR* var, /**< problem variable */
16015  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16016  SCIP_Bool after /**< should the bound change with given index be included? */
16017  )
16018 {
16019  SCIP_VARSTATUS varstatus;
16020  assert(var != NULL);
16021 
16022  varstatus = SCIPvarGetStatus(var);
16023 
16024  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
16025  {
16026  if( bdchgidx == NULL )
16027  return SCIPvarGetLbLocal(var);
16028  else
16029  {
16030  SCIP_BDCHGINFO* bdchginfo;
16031 
16032  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16033  if( bdchginfo != NULL )
16034  return SCIPbdchginfoGetNewbound(bdchginfo);
16035  else
16036  return var->glbdom.lb;
16037  }
16038  }
16039 
16040  /* get bounds of attached variables */
16041  switch( varstatus )
16042  {
16044  assert(var->data.original.transvar != NULL);
16045  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16046 
16047  case SCIP_VARSTATUS_FIXED:
16048  return var->glbdom.lb;
16049 
16050  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16051  assert(var->data.aggregate.var != NULL);
16052  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16053  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16054  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16055  * (or is called by) a public interface method; instead, we only assert that values are finite
16056  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16057  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16058  */
16059  if( var->data.aggregate.scalar > 0.0 )
16060  {
16061  /* a > 0 -> get lower bound of y */
16062  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16063  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16064  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16065  + var->data.aggregate.constant;
16066  }
16067  else if( var->data.aggregate.scalar < 0.0 )
16068  {
16069  /* a < 0 -> get upper bound of y */
16070  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16071  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16072  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16073  + var->data.aggregate.constant;
16074  }
16075  else
16076  {
16077  SCIPerrorMessage("scalar is zero in aggregation\n");
16078  SCIPABORT();
16079  return SCIP_INVALID; /*lint !e527*/
16080  }
16081 
16083  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16084  if ( var->data.multaggr.nvars == 1 )
16085  {
16086  assert(var->data.multaggr.vars != NULL);
16087  assert(var->data.multaggr.scalars != NULL);
16088  assert(var->data.multaggr.vars[0] != NULL);
16089 
16090  if( var->data.multaggr.scalars[0] > 0.0 )
16091  {
16092  /* a > 0 -> get lower bound of y */
16093  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16094  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16095  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16096  + var->data.multaggr.constant;
16097  }
16098  else if( var->data.multaggr.scalars[0] < 0.0 )
16099  {
16100  /* a < 0 -> get upper bound of y */
16101  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16102  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16103  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16104  + var->data.multaggr.constant;
16105  }
16106  else
16107  {
16108  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16109  SCIPABORT();
16110  return SCIP_INVALID; /*lint !e527*/
16111  }
16112  }
16113  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16114  SCIPABORT();
16115  return SCIP_INVALID; /*lint !e527*/
16116 
16117  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16118  assert(var->negatedvar != NULL);
16120  assert(var->negatedvar->negatedvar == var);
16121  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16122 
16123  case SCIP_VARSTATUS_COLUMN: /* for lint */
16124  case SCIP_VARSTATUS_LOOSE: /* for lint */
16125  default:
16126  SCIPerrorMessage("unknown variable status\n");
16127  SCIPABORT();
16128  return SCIP_INVALID; /*lint !e527*/
16129  }
16130 }
16131 
16132 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16133  * was applied
16134  *
16135  * @deprecated Please use SCIPgetVarUbAtIndex()
16136  */
16138  SCIP_VAR* var, /**< problem variable */
16139  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16140  SCIP_Bool after /**< should the bound change with given index be included? */
16141  )
16142 {
16143  SCIP_VARSTATUS varstatus;
16144  assert(var != NULL);
16145 
16146  varstatus = SCIPvarGetStatus(var);
16147 
16148  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
16149  {
16150  if( bdchgidx == NULL )
16151  return SCIPvarGetUbLocal(var);
16152  else
16153  {
16154  SCIP_BDCHGINFO* bdchginfo;
16155 
16156  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16157  if( bdchginfo != NULL )
16158  return SCIPbdchginfoGetNewbound(bdchginfo);
16159  else
16160  return var->glbdom.ub;
16161  }
16162  }
16163 
16164  /* get bounds of attached variables */
16165  switch( varstatus )
16166  {
16168  assert(var->data.original.transvar != NULL);
16169  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16170 
16171  case SCIP_VARSTATUS_FIXED:
16172  return var->glbdom.ub;
16173 
16174  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16175  assert(var->data.aggregate.var != NULL);
16176  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16177  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16178  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16179  * (or is called by) a public interface method; instead, we only assert that values are finite
16180  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16181  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16182  */
16183  if( var->data.aggregate.scalar > 0.0 )
16184  {
16185  /* a > 0 -> get lower bound of y */
16186  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16187  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16188  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16189  + var->data.aggregate.constant;
16190  }
16191  else if( var->data.aggregate.scalar < 0.0 )
16192  {
16193  /* a < 0 -> get upper bound of y */
16194  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16195  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16196  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16197  + var->data.aggregate.constant;
16198  }
16199  else
16200  {
16201  SCIPerrorMessage("scalar is zero in aggregation\n");
16202  SCIPABORT();
16203  return SCIP_INVALID; /*lint !e527*/
16204  }
16205 
16207  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16208  if ( var->data.multaggr.nvars == 1 )
16209  {
16210  assert(var->data.multaggr.vars != NULL);
16211  assert(var->data.multaggr.scalars != NULL);
16212  assert(var->data.multaggr.vars[0] != NULL);
16213 
16214  if( var->data.multaggr.scalars[0] > 0.0 )
16215  {
16216  /* a > 0 -> get lower bound of y */
16217  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16218  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16219  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16220  + var->data.multaggr.constant;
16221  }
16222  else if( var->data.multaggr.scalars[0] < 0.0 )
16223  {
16224  /* a < 0 -> get upper bound of y */
16225  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16226  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16227  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16228  + var->data.multaggr.constant;
16229  }
16230  else
16231  {
16232  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16233  SCIPABORT();
16234  return SCIP_INVALID; /*lint !e527*/
16235  }
16236  }
16237  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16238  SCIPABORT();
16239  return SCIP_INVALID; /*lint !e527*/
16240 
16241  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16242  assert(var->negatedvar != NULL);
16244  assert(var->negatedvar->negatedvar == var);
16245  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16246 
16247  case SCIP_VARSTATUS_COLUMN: /* for lint */
16248  case SCIP_VARSTATUS_LOOSE: /* for lint */
16249  default:
16250  SCIPerrorMessage("unknown variable status\n");
16251  SCIPABORT();
16252  return SCIP_INVALID; /*lint !e527*/
16253  }
16254 }
16255 
16256 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16257  * was applied
16258  *
16259  * @deprecated Please use SCIPgetVarBdAtIndex()
16260  */
16262  SCIP_VAR* var, /**< problem variable */
16263  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16264  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16265  SCIP_Bool after /**< should the bound change with given index be included? */
16266  )
16267 {
16268  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16269  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16270  else
16271  {
16272  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16273  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16274  }
16275 }
16276 
16277 /** returns whether the binary variable was fixed at the time given by the bound change index
16278  *
16279  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16280  */
16282  SCIP_VAR* var, /**< problem variable */
16283  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16284  SCIP_Bool after /**< should the bound change with given index be included? */
16285  )
16286 {
16287  assert(var != NULL);
16288  assert(SCIPvarIsBinary(var));
16289 
16290  /* check the current bounds first in order to decide at which bound change information we have to look
16291  * (which is expensive because we have to follow the aggregation tree to the active variable)
16292  */
16293  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16294  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16295 }
16296 
16297 /** bound change index representing the initial time before any bound changes took place */
16298 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16300 /** bound change index representing the presolving stage */
16301 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16303 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16305  SCIP_VAR* var /**< problem variable */
16306  )
16307 {
16308  SCIP_BDCHGIDX* lbchgidx;
16309  SCIP_BDCHGIDX* ubchgidx;
16310 
16311  assert(var != NULL);
16312 
16313  var = SCIPvarGetProbvar(var);
16314 
16315  /* check, if variable is original without transformed variable */
16316  if( var == NULL )
16317  return &initbdchgidx;
16318 
16319  /* check, if variable was fixed in presolving */
16320  if( !SCIPvarIsActive(var) )
16321  return &presolvebdchgidx;
16322 
16324 
16325  /* get depths of last bound change information for the lower and upper bound */
16326  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16327  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16328  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16329  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16330 
16331  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16332  return ubchgidx;
16333  else
16334  return lbchgidx;
16335 }
16336 
16337 /** returns the last depth level, at which the bounds of the given variable were tightened;
16338  * returns -2, if the variable's bounds are still the global bounds
16339  * returns -1, if the variable was fixed in presolving
16340  */
16342  SCIP_VAR* var /**< problem variable */
16343  )
16344 {
16345  SCIP_BDCHGIDX* bdchgidx;
16346 
16347  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16348  assert(bdchgidx != NULL);
16349 
16350  return bdchgidx->depth;
16351 }
16352 
16353 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16354  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16355  */
16357  SCIP_VAR* var, /**< problem variable */
16358  SCIP_SET* set, /**< global SCIP settings */
16359  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16360  SCIP_Real bound /**< conflicting bound */
16361  )
16362 {
16363  int i;
16364 
16365  assert(var != NULL);
16366  assert(set != NULL);
16367  assert(var->scip == set->scip);
16368 
16369  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16370  {
16371  /* check if the bound is in conflict with the current local bounds */
16372  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16373  return -1;
16374 
16375  /* check if the bound is in conflict with the global bound */
16376  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16377  return 0;
16378 
16379  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16380  assert(var->nubchginfos > 0);
16381  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16382 
16383  /* search for the first conflicting bound change */
16384  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16385  {
16386  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16388  }
16389  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16390  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16391 
16392  /* return the depth at which the first conflicting bound change took place */
16393  return var->ubchginfos[i].bdchgidx.depth;
16394  }
16395  else
16396  {
16397  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16398 
16399  /* check if the bound is in conflict with the current local bounds */
16400  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16401  return -1;
16402 
16403  /* check if the bound is in conflict with the global bound */
16404  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16405  return 0;
16406 
16407  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16408  assert(var->nlbchginfos > 0);
16409  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16410 
16411  /* search for the first conflicting bound change */
16412  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16413  {
16414  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16416  }
16417  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16418  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16419 
16420  /* return the depth at which the first conflicting bound change took place */
16421  return var->lbchginfos[i].bdchgidx.depth;
16422  }
16423 }
16424 
16425 /** returns whether the first binary variable was fixed earlier than the second one;
16426  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16427  * second one is not fixed
16428  */
16430  SCIP_VAR* var1, /**< first binary variable */
16431  SCIP_VAR* var2 /**< second binary variable */
16432  )
16433 {
16434  SCIP_BDCHGIDX* bdchgidx1;
16435  SCIP_BDCHGIDX* bdchgidx2;
16436 
16437  assert(var1 != NULL);
16438  assert(var2 != NULL);
16439  assert(SCIPvarIsBinary(var1));
16440  assert(SCIPvarIsBinary(var2));
16441 
16442  var1 = SCIPvarGetProbvar(var1);
16443  var2 = SCIPvarGetProbvar(var2);
16444  assert(var1 != NULL);
16445  assert(var2 != NULL);
16446 
16447  /* check, if variables are globally fixed */
16448  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16449  return FALSE;
16450  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16451  return TRUE;
16452 
16455  assert(SCIPvarIsBinary(var1));
16456  assert(SCIPvarIsBinary(var2));
16457  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16458  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16459  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16460  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16461  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16462  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16463 
16464  if( var1->nlbchginfos == 1 )
16465  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16466  else if( var1->nubchginfos == 1 )
16467  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16468  else
16469  bdchgidx1 = NULL;
16470 
16471  if( var2->nlbchginfos == 1 )
16472  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16473  else if( var2->nubchginfos == 1 )
16474  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16475  else
16476  bdchgidx2 = NULL;
16477 
16478  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16479 }
16480 
16481 
16482 
16483 /*
16484  * Hash functions
16485  */
16486 
16487 /** gets the key (i.e. the name) of the given variable */
16488 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16489 { /*lint --e{715}*/
16490  SCIP_VAR* var = (SCIP_VAR*)elem;
16491 
16492  assert(var != NULL);
16493  return var->name;
16494 }
16495 
16496 
16497 
16498 
16499 /*
16500  * simple functions implemented as defines
16501  */
16502 
16503 /* In debug mode, the following methods are implemented as function calls to ensure
16504  * type validity.
16505  * In optimized mode, the methods are implemented as defines to improve performance.
16506  * However, we want to have them in the library anyways, so we have to undef the defines.
16507  */
16508 
16509 #undef SCIPboundchgGetNewbound
16510 #undef SCIPboundchgGetVar
16511 #undef SCIPboundchgGetBoundchgtype
16512 #undef SCIPboundchgGetBoundtype
16513 #undef SCIPboundchgIsRedundant
16514 #undef SCIPdomchgGetNBoundchgs
16515 #undef SCIPdomchgGetBoundchg
16516 #undef SCIPholelistGetLeft
16517 #undef SCIPholelistGetRight
16518 #undef SCIPholelistGetNext
16519 #undef SCIPvarGetName
16520 #undef SCIPvarGetNUses
16521 #undef SCIPvarGetData
16522 #undef SCIPvarSetData
16523 #undef SCIPvarSetDelorigData
16524 #undef SCIPvarSetTransData
16525 #undef SCIPvarSetDeltransData
16526 #undef SCIPvarGetStatus
16527 #undef SCIPvarIsOriginal
16528 #undef SCIPvarIsTransformed
16529 #undef SCIPvarIsNegated
16530 #undef SCIPvarGetType
16531 #undef SCIPvarIsBinary
16532 #undef SCIPvarIsIntegral
16533 #undef SCIPvarIsInitial
16534 #undef SCIPvarIsRemovable
16535 #undef SCIPvarIsDeleted
16536 #undef SCIPvarIsDeletable
16537 #undef SCIPvarMarkDeletable
16538 #undef SCIPvarMarkNotDeletable
16539 #undef SCIPvarIsActive
16540 #undef SCIPvarGetIndex
16541 #undef SCIPvarGetProbindex
16542 #undef SCIPvarGetTransVar
16543 #undef SCIPvarGetCol
16544 #undef SCIPvarIsInLP
16545 #undef SCIPvarGetAggrVar
16546 #undef SCIPvarGetAggrScalar
16547 #undef SCIPvarGetAggrConstant
16548 #undef SCIPvarGetMultaggrNVars
16549 #undef SCIPvarGetMultaggrVars
16550 #undef SCIPvarGetMultaggrScalars
16551 #undef SCIPvarGetMultaggrConstant
16552 #undef SCIPvarGetNegatedVar
16553 #undef SCIPvarGetNegationVar
16554 #undef SCIPvarGetNegationConstant
16555 #undef SCIPvarGetObj
16556 #undef SCIPvarGetLbOriginal
16557 #undef SCIPvarGetUbOriginal
16558 #undef SCIPvarGetHolelistOriginal
16559 #undef SCIPvarGetLbGlobal
16560 #undef SCIPvarGetUbGlobal
16561 #undef SCIPvarGetHolelistGlobal
16562 #undef SCIPvarGetBestBoundGlobal
16563 #undef SCIPvarGetWorstBoundGlobal
16564 #undef SCIPvarGetLbLocal
16565 #undef SCIPvarGetUbLocal
16566 #undef SCIPvarGetHolelistLocal
16567 #undef SCIPvarGetBestBoundLocal
16568 #undef SCIPvarGetWorstBoundLocal
16569 #undef SCIPvarGetBestBoundType
16570 #undef SCIPvarGetWorstBoundType
16571 #undef SCIPvarGetLbLazy
16572 #undef SCIPvarGetUbLazy
16573 #undef SCIPvarGetBranchFactor
16574 #undef SCIPvarGetBranchPriority
16575 #undef SCIPvarGetBranchDirection
16576 #undef SCIPvarGetNVlbs
16577 #undef SCIPvarGetVlbVars
16578 #undef SCIPvarGetVlbCoefs
16579 #undef SCIPvarGetVlbConstants
16580 #undef SCIPvarGetNVubs
16581 #undef SCIPvarGetVubVars
16582 #undef SCIPvarGetVubCoefs
16583 #undef SCIPvarGetVubConstants
16584 #undef SCIPvarGetNImpls
16585 #undef SCIPvarGetImplVars
16586 #undef SCIPvarGetImplTypes
16587 #undef SCIPvarGetImplBounds
16588 #undef SCIPvarGetImplIds
16589 #undef SCIPvarGetNCliques
16590 #undef SCIPvarGetCliques
16591 #undef SCIPvarGetLPSol
16592 #undef SCIPvarGetNLPSol
16593 #undef SCIPvarGetBdchgInfoLb
16594 #undef SCIPvarGetNBdchgInfosLb
16595 #undef SCIPvarGetBdchgInfoUb
16596 #undef SCIPvarGetNBdchgInfosUb
16597 #undef SCIPvarGetValuehistory
16598 #undef SCIPvarGetPseudoSol
16599 #undef SCIPvarCatchEvent
16600 #undef SCIPvarDropEvent
16601 #undef SCIPvarGetVSIDS
16602 #undef SCIPvarGetCliqueComponentIdx
16603 #undef SCIPbdchgidxGetPos
16604 #undef SCIPbdchgidxIsEarlierNonNull
16605 #undef SCIPbdchgidxIsEarlier
16606 #undef SCIPbdchginfoGetOldbound
16607 #undef SCIPbdchginfoGetNewbound
16608 #undef SCIPbdchginfoGetVar
16609 #undef SCIPbdchginfoGetChgtype
16610 #undef SCIPbdchginfoGetBoundtype
16611 #undef SCIPbdchginfoGetDepth
16612 #undef SCIPbdchginfoGetPos
16613 #undef SCIPbdchginfoGetIdx
16614 #undef SCIPbdchginfoGetInferVar
16615 #undef SCIPbdchginfoGetInferCons
16616 #undef SCIPbdchginfoGetInferProp
16617 #undef SCIPbdchginfoGetInferInfo
16618 #undef SCIPbdchginfoGetInferBoundtype
16619 #undef SCIPbdchginfoIsRedundant
16620 #undef SCIPbdchginfoHasInferenceReason
16621 #undef SCIPbdchginfoIsTighter
16622 
16623 
16624 /** returns the new value of the bound in the bound change data */
16626  SCIP_BOUNDCHG* boundchg /**< bound change data */
16627  )
16628 {
16629  assert(boundchg != NULL);
16630 
16631  return boundchg->newbound;
16632 }
16633 
16634 /** returns the variable of the bound change in the bound change data */
16636  SCIP_BOUNDCHG* boundchg /**< bound change data */
16637  )
16638 {
16639  assert(boundchg != NULL);
16640 
16641  return boundchg->var;
16642 }
16643 
16644 /** returns the bound change type of the bound change in the bound change data */
16646  SCIP_BOUNDCHG* boundchg /**< bound change data */
16647  )
16648 {
16649  assert(boundchg != NULL);
16650 
16651  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16652 }
16653 
16654 /** returns the bound type of the bound change in the bound change data */
16656  SCIP_BOUNDCHG* boundchg /**< bound change data */
16657  )
16658 {
16659  assert(boundchg != NULL);
16660 
16661  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16662 }
16663 
16664 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16666  SCIP_BOUNDCHG* boundchg /**< bound change data */
16667  )
16668 {
16669  assert(boundchg != NULL);
16670 
16671  return boundchg->redundant;
16672 }
16673 
16674 /** returns the number of bound changes in the domain change data */
16676  SCIP_DOMCHG* domchg /**< domain change data */
16677  )
16678 {
16679  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16680 }
16681 
16682 /** returns a particular bound change in the domain change data */
16684  SCIP_DOMCHG* domchg, /**< domain change data */
16685  int pos /**< position of the bound change in the domain change data */
16686  )
16687 {
16688  assert(domchg != NULL);
16689  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16690 
16691  return &domchg->domchgbound.boundchgs[pos];
16692 }
16693 
16694 /** returns left bound of open interval in hole */
16696  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16697  )
16698 {
16699  assert(holelist != NULL);
16700 
16701  return holelist->hole.left;
16702 }
16703 
16704 /** returns right bound of open interval in hole */
16706  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16707  )
16708 {
16709  assert(holelist != NULL);
16710 
16711  return holelist->hole.right;
16712 }
16713 
16714 /** returns next hole in list */
16716  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16717  )
16718 {
16719  assert(holelist != NULL);
16720 
16721  return holelist->next;
16722 }
16723 
16724 /** returns the name of the variable
16725  *
16726  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16727  */
16728 const char* SCIPvarGetName(
16729  SCIP_VAR* var /**< problem variable */
16730  )
16731 {
16732  assert(var != NULL);
16733 
16734  return var->name;
16735 }
16736 
16737 /** gets number of times, the variable is currently captured */
16738 int SCIPvarGetNUses(
16739  SCIP_VAR* var /**< problem variable */
16740  )
16741 {
16742  assert(var != NULL);
16743 
16744  return var->nuses;
16745 }
16746 
16747 /** returns the user data of the variable */
16749  SCIP_VAR* var /**< problem variable */
16750  )
16751 {
16752  assert(var != NULL);
16753 
16754  return var->vardata;
16755 }
16756 
16757 /** sets the user data for the variable */
16758 void SCIPvarSetData(
16759  SCIP_VAR* var, /**< problem variable */
16760  SCIP_VARDATA* vardata /**< user variable data */
16761  )
16762 {
16763  assert(var != NULL);
16764 
16765  var->vardata = vardata;
16766 }
16767 
16768 /** sets method to free user data for the original variable */
16770  SCIP_VAR* var, /**< problem variable */
16771  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16772  )
16773 {
16774  assert(var != NULL);
16775  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16776 
16777  var->vardelorig = vardelorig;
16778 }
16779 
16780 /** sets method to transform user data of the variable */
16781 void SCIPvarSetTransData(
16782  SCIP_VAR* var, /**< problem variable */
16783  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16784  )
16785 {
16786  assert(var != NULL);
16787  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16788 
16789  var->vartrans = vartrans;
16790 }
16791 
16792 /** sets method to free transformed user data for the variable */
16794  SCIP_VAR* var, /**< problem variable */
16795  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16796  )
16797 {
16798  assert(var != NULL);
16799 
16800  var->vardeltrans = vardeltrans;
16801 }
16802 
16803 /** sets method to copy this variable into sub-SCIPs */
16804 void SCIPvarSetCopyData(
16805  SCIP_VAR* var, /**< problem variable */
16806  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16807  )
16808 {
16809  assert(var != NULL);
16810 
16811  var->varcopy = varcopy;
16812 }
16813 
16814 /** sets the initial flag of a variable; only possible for original or loose variables */
16816  SCIP_VAR* var, /**< problem variable */
16817  SCIP_Bool initial /**< initial flag */
16818  )
16819 {
16820  assert(var != NULL);
16821 
16823  return SCIP_INVALIDCALL;
16824 
16825  var->initial = initial;
16826 
16827  return SCIP_OKAY;
16828 }
16829 
16830 /** sets the removable flag of a variable; only possible for original or loose variables */
16832  SCIP_VAR* var, /**< problem variable */
16833  SCIP_Bool removable /**< removable flag */
16834  )
16835 {
16836  assert(var != NULL);
16837 
16839  return SCIP_INVALIDCALL;
16840 
16841  var->removable = removable;
16842 
16843  return SCIP_OKAY;
16844 }
16845 
16846 /** gets status of variable */
16848  SCIP_VAR* var /**< problem variable */
16849  )
16850 {
16851  assert(var != NULL);
16852 
16853  return (SCIP_VARSTATUS)(var->varstatus);
16854 }
16855 
16856 /** returns whether the variable belongs to the original problem */
16858  SCIP_VAR* var /**< problem variable */
16859  )
16860 {
16861  assert(var != NULL);
16862  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16863 
16867 }
16868 
16869 /** returns whether the variable belongs to the transformed problem */
16871  SCIP_VAR* var /**< problem variable */
16872  )
16873 {
16874  assert(var != NULL);
16875  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16876 
16880 }
16881 
16882 /** returns whether the variable was created by negation of a different variable */
16884  SCIP_VAR* var /**< problem variable */
16885  )
16886 {
16887  assert(var != NULL);
16888 
16889  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16890 }
16891 
16892 /** gets type of variable */
16894  SCIP_VAR* var /**< problem variable */
16895  )
16896 {
16897  assert(var != NULL);
16898 
16899  return (SCIP_VARTYPE)(var->vartype);
16900 }
16901 
16902 /** returns TRUE if the variable is of binary type; this is the case if:
16903  * (1) variable type is binary
16904  * (2) variable type is integer or implicit integer and
16905  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16906  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16907  */
16909  SCIP_VAR* var /**< problem variable */
16910  )
16911 {
16912  assert(var != NULL);
16913 
16914  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16915  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16916 }
16917 
16918 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16920  SCIP_VAR* var /**< problem variable */
16921  )
16922 {
16923  assert(var != NULL);
16924 
16925  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16926 }
16927 
16928 /** returns whether variable's column should be present in the initial root LP */
16930  SCIP_VAR* var /**< problem variable */
16931  )
16932 {
16933  assert(var != NULL);
16934 
16935  return var->initial;
16936 }
16937 
16938 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16940  SCIP_VAR* var /**< problem variable */
16941  )
16942 {
16943  assert(var != NULL);
16944 
16945  return var->removable;
16946 }
16947 
16948 /** returns whether the variable was deleted from the problem */
16950  SCIP_VAR* var /**< problem variable */
16951  )
16952 {
16953  assert(var != NULL);
16954 
16955  return var->deleted;
16956 }
16957 
16958 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16959  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16960  */
16962  SCIP_VAR* var /**< problem variable */
16963  )
16964 {
16965  assert(var != NULL);
16966  assert(var->probindex == -1);
16967 
16968  var->deletable = TRUE;
16969 }
16970 
16971 /** marks the variable to be not deletable from the problem */
16974  )
16975 {
16976  assert(var != NULL);
16977 
16978  var->deletable = FALSE;
16979 }
16980 
16981 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16982  *
16983  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16984  */
16986  SCIP_VAR* var /**< problem variable */
16987  )
16988 {
16989  assert(var != NULL);
16990 
16991  var->delglobalstructs = TRUE;
16992 }
16993 
16994 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16996  SCIP_VAR* var /**< problem variable */
16997  )
16998 {
16999  assert(var != NULL);
17000 
17001  return var->delglobalstructs;
17002 }
17003 
17004 /** returns whether variable is allowed to be deleted completely from the problem */
17007  )
17008 {
17009  assert(var != NULL);
17010 
17011  return var->deletable;
17012 }
17013 
17014 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17016  SCIP_VAR* var /**< problem variable */
17017  )
17018 {
17019  assert(var != NULL);
17020 
17021  return (var->probindex >= 0);
17022 }
17023 
17024 /** gets unique index of variable */
17025 int SCIPvarGetIndex(
17026  SCIP_VAR* var /**< problem variable */
17027  )
17028 {
17029  assert(var != NULL);
17030 
17031  return var->index;
17032 }
17033 
17034 /** gets position of variable in problem, or -1 if variable is not active */
17036  SCIP_VAR* var /**< problem variable */
17037  )
17038 {
17039  assert(var != NULL);
17040 
17041  return var->probindex;
17042 }
17043 
17044 /** gets transformed variable of ORIGINAL variable */
17046  SCIP_VAR* var /**< problem variable */
17047  )
17048 {
17049  assert(var != NULL);
17050  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17051 
17052  return var->data.original.transvar;
17053 }
17054 
17055 /** gets column of COLUMN variable */
17057  SCIP_VAR* var /**< problem variable */
17058  )
17059 {
17060  assert(var != NULL);
17061  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17062 
17063  return var->data.col;
17064 }
17065 
17066 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17068  SCIP_VAR* var /**< problem variable */
17069  )
17070 {
17071  assert(var != NULL);
17072 
17073  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17074 }
17075 
17076 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17078  SCIP_VAR* var /**< problem variable */
17079  )
17080 {
17081  assert(var != NULL);
17083 
17084  return var->data.aggregate.var;
17085 }
17086 
17087 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17089  SCIP_VAR* var /**< problem variable */
17090  )
17091 {
17092  assert(var != NULL);
17094 
17095  return var->data.aggregate.scalar;
17096 }
17097 
17098 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17100  SCIP_VAR* var /**< problem variable */
17101  )
17102 {
17103  assert(var != NULL);
17105 
17106  return var->data.aggregate.constant;
17107 }
17108 
17109 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17111  SCIP_VAR* var /**< problem variable */
17112  )
17113 {
17114  assert(var != NULL);
17115  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17116  assert(!var->donotmultaggr);
17117 
17118  return var->data.multaggr.nvars;
17119 }
17120 
17121 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17123  SCIP_VAR* var /**< problem variable */
17124  )
17125 {
17126  assert(var != NULL);
17127  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17128  assert(!var->donotmultaggr);
17129 
17130  return var->data.multaggr.vars;
17131 }
17132 
17133 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17135  SCIP_VAR* var /**< problem variable */
17136  )
17137 {
17138  assert(var != NULL);
17139  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17140  assert(!var->donotmultaggr);
17141 
17142  return var->data.multaggr.scalars;
17143 }
17144 
17145 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17147  SCIP_VAR* var /**< problem variable */
17148  )
17149 {
17150  assert(var != NULL);
17151  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17152  assert(!var->donotmultaggr);
17153 
17154  return var->data.multaggr.constant;
17155 }
17156 
17157 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17159  SCIP_VAR* var /**< negated problem variable */
17160  )
17161 {
17162  assert(var != NULL);
17163 
17164  return var->negatedvar;
17165 }
17166 
17167 /** gets the negation variable x of a negated variable x' = offset - x */
17169  SCIP_VAR* var /**< negated problem variable */
17170  )
17171 {
17172  assert(var != NULL);
17173  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17174 
17175  return var->negatedvar;
17176 }
17177 
17178 /** gets the negation offset of a negated variable x' = offset - x */
17180  SCIP_VAR* var /**< negated problem variable */
17181  )
17182 {
17183  assert(var != NULL);
17184  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17185 
17186  return var->data.negate.constant;
17187 }
17188 
17189 /** gets objective function value of variable */
17191  SCIP_VAR* var /**< problem variable */
17192  )
17193 {
17194  assert(var != NULL);
17195 
17196  return var->obj;
17197 }
17198 
17199 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17201  SCIP_VAR* var /**< problem variable */
17202  )
17203 {
17204  assert(var != NULL);
17205 
17206  return var->unchangedobj;
17207 }
17208 
17209 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17210  * e.g. obj(x) = 1 this method returns for ~x the value -1
17211  */
17213  SCIP_VAR* var, /**< problem variable */
17214  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17215  )
17216 {
17217  SCIP_VAR* probvar = var;
17218  SCIP_Real mult = 1.0;
17219 
17220  assert(probvar != NULL);
17221  assert(aggrobj != NULL);
17222 
17223  while( probvar != NULL )
17224  {
17225  switch( SCIPvarGetStatus(probvar) )
17226  {
17228  case SCIP_VARSTATUS_LOOSE:
17229  case SCIP_VARSTATUS_COLUMN:
17230  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17231  return SCIP_OKAY;
17232 
17233  case SCIP_VARSTATUS_FIXED:
17234  assert(SCIPvarGetObj(probvar) == 0.0);
17235  (*aggrobj) = 0.0;
17236  return SCIP_OKAY;
17237 
17239  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17240  if ( probvar->data.multaggr.nvars == 1 )
17241  {
17242  assert( probvar->data.multaggr.vars != NULL );
17243  assert( probvar->data.multaggr.scalars != NULL );
17244  assert( probvar->data.multaggr.vars[0] != NULL );
17245  mult *= probvar->data.multaggr.scalars[0];
17246  probvar = probvar->data.multaggr.vars[0];
17247  break;
17248  }
17249  else
17250  {
17251  SCIP_Real tmpobj;
17252  int v;
17253 
17254  (*aggrobj) = 0.0;
17255 
17256  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17257  {
17258  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17259  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17260  }
17261  return SCIP_OKAY;
17262  }
17263 
17264  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17265  assert(probvar->data.aggregate.var != NULL);
17266  mult *= probvar->data.aggregate.scalar;
17267  probvar = probvar->data.aggregate.var;
17268  break;
17269 
17270  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17271  assert(probvar->negatedvar != NULL);
17272  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17273  assert(probvar->negatedvar->negatedvar == probvar);
17274  mult *= -1.0;
17275  probvar = probvar->negatedvar;
17276  break;
17277 
17278  default:
17279  SCIPABORT();
17280  return SCIP_INVALIDDATA; /*lint !e527*/
17281  }
17282  }
17283 
17284  return SCIP_INVALIDDATA;
17285 }
17286 
17287 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17289  SCIP_VAR* var /**< original problem variable */
17290  )
17291 {
17292  assert(var != NULL);
17293  assert(SCIPvarIsOriginal(var));
17294 
17296  return var->data.original.origdom.lb;
17297  else
17298  {
17299  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17300  assert(var->negatedvar != NULL);
17302 
17303  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17304  }
17305 }
17306 
17307 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17309  SCIP_VAR* var /**< original problem variable */
17310  )
17311 {
17312  assert(var != NULL);
17313  assert(SCIPvarIsOriginal(var));
17314 
17316  return var->data.original.origdom.ub;
17317  else
17318  {
17319  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17320  assert(var->negatedvar != NULL);
17322 
17323  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17324  }
17325 }
17326 
17327 /** gets the original hole list of an original variable */
17329  SCIP_VAR* var /**< problem variable */
17330  )
17331 {
17332  assert(var != NULL);
17333  assert(SCIPvarIsOriginal(var));
17334 
17336  return var->data.original.origdom.holelist;
17337 
17338  return NULL;
17339 }
17340 
17341 /** gets global lower bound of variable */
17343  SCIP_VAR* var /**< problem variable */
17344  )
17345 {
17346  assert(var != NULL);
17347 
17348  return var->glbdom.lb;
17349 }
17350 
17351 /** gets global upper bound of variable */
17353  SCIP_VAR* var /**< problem variable */
17354  )
17355 {
17356  assert(var != NULL);
17357 
17358  return var->glbdom.ub;
17359 }
17360 
17361 /** gets the global hole list of an active variable */
17363  SCIP_VAR* var /**< problem variable */
17364  )
17365 {
17366  assert(var != NULL);
17367 
17368  return var->glbdom.holelist;
17369 }
17370 
17371 /** gets best global bound of variable with respect to the objective function */
17373  SCIP_VAR* var /**< problem variable */
17374  )
17375 {
17376  assert(var != NULL);
17377 
17378  if( var->obj >= 0.0 )
17379  return var->glbdom.lb;
17380  else
17381  return var->glbdom.ub;
17382 }
17383 
17384 /** gets worst global bound of variable with respect to the objective function */
17386  SCIP_VAR* var /**< problem variable */
17387  )
17388 {
17389  assert(var != NULL);
17390 
17391  if( var->obj >= 0.0 )
17392  return var->glbdom.ub;
17393  else
17394  return var->glbdom.lb;
17395 }
17396 
17397 /** gets current lower bound of variable */
17399  SCIP_VAR* var /**< problem variable */
17400  )
17401 {
17402  assert(var != NULL);
17403 
17404  return var->locdom.lb;
17405 }
17406 
17407 /** gets current upper bound of variable */
17409  SCIP_VAR* var /**< problem variable */
17410  )
17411 {
17412  assert(var != NULL);
17413 
17414  return var->locdom.ub;
17415 }
17416 
17417 /** gets the current hole list of an active variable */
17419  SCIP_VAR* var /**< problem variable */
17420  )
17421 {
17422  assert(var != NULL);
17423 
17424  return var->locdom.holelist;
17425 }
17426 
17427 /** gets best local bound of variable with respect to the objective function */
17429  SCIP_VAR* var /**< problem variable */
17430  )
17431 {
17432  assert(var != NULL);
17433 
17434  if( var->obj >= 0.0 )
17435  return var->locdom.lb;
17436  else
17437  return var->locdom.ub;
17438 }
17439 
17440 /** gets worst local bound of variable with respect to the objective function */
17442  SCIP_VAR* var /**< problem variable */
17443  )
17444 {
17445  assert(var != NULL);
17446 
17447  if( var->obj >= 0.0 )
17448  return var->locdom.ub;
17449  else
17450  return var->locdom.lb;
17451 }
17452 
17453 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17455  SCIP_VAR* var /**< problem variable */
17456  )
17457 {
17458  assert(var != NULL);
17459 
17460  if( var->obj >= 0.0 )
17461  return SCIP_BOUNDTYPE_LOWER;
17462  else
17463  return SCIP_BOUNDTYPE_UPPER;
17464 }
17465 
17466 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17468  SCIP_VAR* var /**< problem variable */
17469  )
17470 {
17471  assert(var != NULL);
17472 
17473  if( var->obj >= 0.0 )
17474  return SCIP_BOUNDTYPE_UPPER;
17475  else
17476  return SCIP_BOUNDTYPE_LOWER;
17477 }
17478 
17479 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17481  SCIP_VAR* var /**< problem variable */
17482  )
17483 {
17484  assert(var != NULL);
17485 
17486  return var->lazylb;
17487 }
17488 
17489 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17491  SCIP_VAR* var /**< problem variable */
17492  )
17493 {
17494  assert(var != NULL);
17495 
17496  return var->lazyub;
17497 }
17498 
17499 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17500  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17501  */
17503  SCIP_VAR* var /**< problem variable */
17504  )
17505 {
17506  assert(var != NULL);
17507 
17508  return var->branchfactor;
17509 }
17510 
17511 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17512  * with lower priority
17513  */
17515  SCIP_VAR* var /**< problem variable */
17516  )
17517 {
17518  assert(var != NULL);
17519 
17520  return var->branchpriority;
17521 }
17522 
17523 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17525  SCIP_VAR* var /**< problem variable */
17526  )
17527 {
17528  assert(var != NULL);
17529 
17530  return (SCIP_BRANCHDIR)var->branchdirection;
17531 }
17532 
17533 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17534 int SCIPvarGetNVlbs(
17535  SCIP_VAR* var /**< problem variable */
17536  )
17537 {
17538  assert(var != NULL);
17539 
17540  return SCIPvboundsGetNVbds(var->vlbs);
17541 }
17542 
17543 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17544  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17545  */
17547  SCIP_VAR* var /**< problem variable */
17548  )
17549 {
17550  assert(var != NULL);
17551 
17552  return SCIPvboundsGetVars(var->vlbs);
17553 }
17554 
17555 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17557  SCIP_VAR* var /**< problem variable */
17558  )
17559 {
17560  assert(var != NULL);
17561 
17562  return SCIPvboundsGetCoefs(var->vlbs);
17563 }
17564 
17565 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17567  SCIP_VAR* var /**< problem variable */
17568  )
17569 {
17570  assert(var != NULL);
17571 
17572  return SCIPvboundsGetConstants(var->vlbs);
17573 }
17574 
17575 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17576 int SCIPvarGetNVubs(
17577  SCIP_VAR* var /**< problem variable */
17578  )
17579 {
17580  assert(var != NULL);
17581 
17582  return SCIPvboundsGetNVbds(var->vubs);
17583 }
17584 
17585 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17586  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17587  */
17589  SCIP_VAR* var /**< problem variable */
17590  )
17591 {
17592  assert(var != NULL);
17593 
17594  return SCIPvboundsGetVars(var->vubs);
17595 }
17596 
17597 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17599  SCIP_VAR* var /**< problem variable */
17600  )
17601 {
17602  assert(var != NULL);
17603 
17604  return SCIPvboundsGetCoefs(var->vubs);
17605 }
17606 
17607 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17609  SCIP_VAR* var /**< problem variable */
17610  )
17611 {
17612  assert(var != NULL);
17613 
17614  return SCIPvboundsGetConstants(var->vubs);
17615 }
17616 
17617 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17618  * there are no implications for nonbinary variable x
17619  */
17620 int SCIPvarGetNImpls(
17621  SCIP_VAR* var, /**< active problem variable */
17622  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17623  )
17624 {
17625  assert(var != NULL);
17626  assert(SCIPvarIsActive(var));
17627 
17628  return SCIPimplicsGetNImpls(var->implics, varfixing);
17629 }
17630 
17631 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17632  * problem variable x, there are no implications for nonbinary variable x;
17633  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17634  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17635  * (see SCIPvarGetIndex())
17636  */
17638  SCIP_VAR* var, /**< active problem variable */
17639  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17640  )
17641 {
17642  assert(var != NULL);
17643  assert(SCIPvarIsActive(var));
17644 
17645  return SCIPimplicsGetVars(var->implics, varfixing);
17646 }
17647 
17648 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17649  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17650  * there are no implications for nonbinary variable x
17651  */
17653  SCIP_VAR* var, /**< active problem variable */
17654  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17655  )
17656 {
17657  assert(var != NULL);
17658  assert(SCIPvarIsActive(var));
17659 
17660  return SCIPimplicsGetTypes(var->implics, varfixing);
17661 }
17662 
17663 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17664  * variable x, there are no implications for nonbinary variable x
17665  */
17667  SCIP_VAR* var, /**< active problem variable */
17668  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17669  )
17670 {
17671  assert(var != NULL);
17672  assert(SCIPvarIsActive(var));
17673 
17674  return SCIPimplicsGetBounds(var->implics, varfixing);
17675 }
17676 
17677 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17678  * there are no implications for nonbinary variable x.
17679  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17680  * its id is negative, otherwise it is nonnegative.
17681  */
17682 int* SCIPvarGetImplIds(
17683  SCIP_VAR* var, /**< active problem variable */
17684  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17685  )
17686 {
17687  assert(var != NULL);
17688  assert(SCIPvarIsActive(var));
17689 
17690  return SCIPimplicsGetIds(var->implics, varfixing);
17691 }
17692 
17693 /** gets number of cliques, the active variable is contained in */
17694 int SCIPvarGetNCliques(
17695  SCIP_VAR* var, /**< active problem variable */
17696  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17697  )
17698 {
17699  assert(var != NULL);
17700 
17701  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17702 }
17703 
17704 /** gets array of cliques, the active variable is contained in */
17706  SCIP_VAR* var, /**< active problem variable */
17707  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17708  )
17709 {
17710  assert(var != NULL);
17711 
17712  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17713 }
17714 
17715 /** gets primal LP solution value of variable */
17717  SCIP_VAR* var /**< problem variable */
17718  )
17719 {
17720  assert(var != NULL);
17721 
17723  return SCIPcolGetPrimsol(var->data.col);
17724  else
17725  return SCIPvarGetLPSol_rec(var);
17726 }
17727 
17728 /** gets primal NLP solution value of variable */
17730  SCIP_VAR* var /**< problem variable */
17731  )
17732 {
17733  assert(var != NULL);
17734 
17736  return var->nlpsol;
17737  else
17738  return SCIPvarGetNLPSol_rec(var);
17739 }
17740 
17741 /** return lower bound change info at requested position */
17743  SCIP_VAR* var, /**< problem variable */
17744  int pos /**< requested position */
17745  )
17746 {
17747  assert(pos >= 0);
17748  assert(pos < var->nlbchginfos);
17749 
17750  return &var->lbchginfos[pos];
17751 }
17752 
17753 /** gets the number of lower bound change info array */
17755  SCIP_VAR* var /**< problem variable */
17756  )
17757 {
17758  return var->nlbchginfos;
17759 }
17760 
17761 /** return upper bound change info at requested position */
17763  SCIP_VAR* var, /**< problem variable */
17764  int pos /**< requested position */
17765  )
17766 {
17767  assert(pos >= 0);
17768  assert(pos < var->nubchginfos);
17769 
17770  return &var->ubchginfos[pos];
17771 }
17772 
17773 /** gets the number upper bound change info array */
17775  SCIP_VAR* var /**< problem variable */
17776  )
17777 {
17778  assert(var != NULL);
17779 
17780  return var->nubchginfos;
17781 }
17782 
17783 /** returns the value based history for the variable */
17785  SCIP_VAR* var /**< problem variable */
17786  )
17787 {
17788  assert(var != NULL);
17789 
17790  return var->valuehistory;
17791 }
17792 
17793 /** gets pseudo solution value of variable */
17795  SCIP_VAR* var /**< problem variable */
17796  )
17797 {
17798  assert(var != NULL);
17799 
17801  return SCIPvarGetBestBoundLocal(var);
17802  else
17803  return SCIPvarGetPseudoSol_rec(var);
17804 }
17805 
17806 /** returns the variable's VSIDS score */
17808  SCIP_VAR* var, /**< problem variable */
17809  SCIP_STAT* stat, /**< problem statistics */
17810  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17811  )
17812 {
17813  assert(var != NULL);
17814 
17816  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17817  else
17818  return SCIPvarGetVSIDS_rec(var, stat, dir);
17819 }
17820 
17821 /** includes event handler with given data in variable's event filter */
17823  SCIP_VAR* var, /**< problem variable */
17824  BMS_BLKMEM* blkmem, /**< block memory */
17825  SCIP_SET* set, /**< global SCIP settings */
17826  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17827  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17828  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17829  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17830  )
17831 {
17832  assert(var != NULL);
17833  assert(set != NULL);
17834  assert(var->scip == set->scip);
17835  assert(var->eventfilter != NULL);
17836  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17837  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17838  assert(SCIPvarIsTransformed(var));
17839 
17840  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
17841  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17842 
17843  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17844 
17845  return SCIP_OKAY;
17846 }
17847 
17848 /** deletes event handler with given data from variable's event filter */
17850  SCIP_VAR* var, /**< problem variable */
17851  BMS_BLKMEM* blkmem, /**< block memory */
17852  SCIP_SET* set, /**< global SCIP settings */
17853  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17854  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17855  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17856  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17857  )
17858 {
17859  assert(var != NULL);
17860  assert(set != NULL);
17861  assert(var->scip == set->scip);
17862  assert(var->eventfilter != NULL);
17863  assert(SCIPvarIsTransformed(var));
17864 
17865  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17866  (void*)eventdata);
17867 
17868  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17869 
17870  return SCIP_OKAY;
17871 }
17872 
17873 /** returns the position of the bound change index */
17874 int SCIPbdchgidxGetPos(
17875  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17876  )
17877 {
17878  assert(bdchgidx != NULL);
17879 
17880  return bdchgidx->pos;
17881 }
17882 
17883 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17885  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17886  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17887  )
17888 {
17889  assert(bdchgidx1 != NULL);
17890  assert(bdchgidx1->depth >= -2);
17891  assert(bdchgidx1->pos >= 0);
17892  assert(bdchgidx2 != NULL);
17893  assert(bdchgidx2->depth >= -2);
17894  assert(bdchgidx2->pos >= 0);
17895 
17896  return (bdchgidx1->depth < bdchgidx2->depth)
17897  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17898 }
17899 
17900 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17901  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17902  * last bound change was applied to the current node
17903  */
17905  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17906  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17907  )
17908 {
17909  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17910  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17911  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17912  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17913 
17914  if( bdchgidx1 == NULL )
17915  return FALSE;
17916  else if( bdchgidx2 == NULL )
17917  return TRUE;
17918  else
17919  return (bdchgidx1->depth < bdchgidx2->depth)
17920  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17921 }
17922 
17923 /** returns old bound that was overwritten for given bound change information */
17925  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17926  )
17927 {
17928  assert(bdchginfo != NULL);
17929 
17930  return bdchginfo->oldbound;
17931 }
17932 
17933 /** returns new bound installed for given bound change information */
17935  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17936  )
17937 {
17938  assert(bdchginfo != NULL);
17939 
17940  return bdchginfo->newbound;
17941 }
17942 
17943 /** returns variable that belongs to the given bound change information */
17945  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17946  )
17947 {
17948  assert(bdchginfo != NULL);
17949 
17950  return bdchginfo->var;
17951 }
17952 
17953 /** returns whether the bound change information belongs to a branching decision or a deduction */
17955  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17956  )
17957 {
17958  assert(bdchginfo != NULL);
17959 
17960  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17961 }
17962 
17963 /** returns whether the bound change information belongs to a lower or upper bound change */
17965  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17966  )
17967 {
17968  assert(bdchginfo != NULL);
17969 
17970  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17971 }
17972 
17973 /** returns depth level of given bound change information */
17975  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17976  )
17977 {
17978  assert(bdchginfo != NULL);
17979 
17980  return bdchginfo->bdchgidx.depth;
17981 }
17982 
17983 /** returns bound change position in its depth level of given bound change information */
17985  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17986  )
17987 {
17988  assert(bdchginfo != NULL);
17989 
17990  return bdchginfo->bdchgidx.pos;
17991 }
17992 
17993 /** returns bound change index of given bound change information */
17995  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17996  )
17997 {
17998  assert(bdchginfo != NULL);
17999 
18000  return &bdchginfo->bdchgidx;
18001 }
18002 
18003 /** returns inference variable of given bound change information */
18005  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18006  )
18007 {
18008  assert(bdchginfo != NULL);
18011 
18012  return bdchginfo->inferencedata.var;
18013 }
18014 
18015 /** returns inference constraint of given bound change information */
18017  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18018  )
18019 {
18020  assert(bdchginfo != NULL);
18022  assert(bdchginfo->inferencedata.reason.cons != NULL);
18023 
18024  return bdchginfo->inferencedata.reason.cons;
18025 }
18026 
18027 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18029  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18030  )
18031 {
18032  assert(bdchginfo != NULL);
18034 
18035  return bdchginfo->inferencedata.reason.prop;
18036 }
18037 
18038 /** returns inference user information of given bound change information */
18040  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18041  )
18042 {
18043  assert(bdchginfo != NULL);
18046 
18047  return bdchginfo->inferencedata.info;
18048 }
18049 
18050 /** returns inference bound of inference variable of given bound change information */
18052  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18053  )
18054 {
18055  assert(bdchginfo != NULL);
18058 
18059  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18060 }
18061 
18062 /** returns the relaxed bound change type */
18064  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18065  )
18066 {
18067  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18068 }
18069 
18070 
18071 /** returns whether the bound change information belongs to a redundant bound change */
18073  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18074  )
18075 {
18076  assert(bdchginfo != NULL);
18077  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18078 
18079  return bdchginfo->redundant;
18080 }
18081 
18082 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18084  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18085  )
18086 {
18087  assert(bdchginfo != NULL);
18088 
18091  && bdchginfo->inferencedata.reason.prop != NULL);
18092 }
18093 
18094 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18095  * has a tighter new bound as the second bound change
18096  */
18098  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18099  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18100  )
18101 {
18102  assert(bdchginfo1 != NULL);
18103  assert(bdchginfo2 != NULL);
18104  assert(bdchginfo1->var == bdchginfo2->var);
18105  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18106 
18107  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18108  ? bdchginfo1->newbound > bdchginfo2->newbound
18109  : bdchginfo1->newbound < bdchginfo2->newbound);
18110 }
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:18064
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:14877
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17442
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5953
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17557
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:449
#define NULL
Definition: def.h:239
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13597
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:17468
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9084
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:15004
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10958
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:14524
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8966
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:10075
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16262
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18029
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16973
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12757
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13481
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:17377
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:6045
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17743
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17135
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:15783
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:17503
unsigned int inferboundtype
Definition: struct_var.h:93
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17925
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:17525
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:17491
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:6539
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6351
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17535
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17945
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1906
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17386
#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:6889
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5661
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:14091
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:16342
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:17343
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15260
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11789
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:14257
#define SCIP_MAXSTRLEN
Definition: def.h:260
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:16628
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16930
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:6271
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:17123
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:262
#define MAXABSVBCOEF
Definition: var.c:70
#define SQR(x)
Definition: def.h:191
#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:12891
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15837
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:17399
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7173
SCIP_Real constant
Definition: struct_var.h:184
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17706
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:8268
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:17785
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3409
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7624
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1425
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16782
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6330
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:8576
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:16909
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:6466
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:12734
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:17905
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16282
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17429
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12827
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:5884
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14610
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12411
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:16656
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:17823
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:5804
#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:16716
#define FALSE
Definition: def.h:65
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:175
#define EPSISINT(x, eps)
Definition: def.h:187
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17367
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:17755
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:16570
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:16550
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:10017
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:14496
#define TRUE
Definition: def.h:64
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10629
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5785
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14833
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:17180
#define MAXIMPLSCLOSURE
Definition: var.c:67
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17577
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:18040
int nlbchginfos
Definition: struct_var.h:261
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16302
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:17036
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:10430
#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:7951
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5819
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:7925
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17089
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:7032
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15450
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16962
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:15538
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:10753
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17547
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:11486
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17875
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:17006
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16357
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13852
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1911
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15217
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16940
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6221
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:261
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11299
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:17169
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:13470
#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:16305
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17695
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12548
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:15693
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17683
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17329
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:11479
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:12481
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:7250
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:166
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17159
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1123
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15399
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:8727
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12620
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17775
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:7344
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18098
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:7674
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17353
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:11697
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12365
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:5919
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13291
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:10979
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:12944
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:16770
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11169
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13950
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:443
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16593
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:7288
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:16794
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7196
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17373
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:7508
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:12940
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16666
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14118
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17289
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:16299
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:14400
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:17885
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:5970
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11384
int lbchginfossize
Definition: struct_var.h:260
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15305
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:17309
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12340
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:6158
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11414
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13999
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16138
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:10148
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10649
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
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:17609
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:6715
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:17100
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16560
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16729
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:4869
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:11465
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:13672
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:7341
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13337
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:165
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16626
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3269
#define REALABS(x)
Definition: def.h:174
int nparentvars
Definition: struct_var.h:255
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17717
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:17363
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:9703
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14741
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:17213
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14219
#define SCIP_CALL(x)
Definition: def.h:351
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18084
SCIP_VBOUNDS * vubs
Definition: struct_var.h:238
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17481
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:17567
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:14920
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17147
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2346
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14046
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:9422
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5612
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3277
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15650
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17599
Definition: grphload.c:88
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18073
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:14134
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:11113
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:7800
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:257
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17995
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14788
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:258
#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:13322
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:6255
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:446
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16858
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:5943
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11043
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:5095
#define SCIP_UNKNOWN
Definition: def.h:171
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:17653
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:450
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:15088
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:6390
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:16706
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:8695
#define SCIP_Bool
Definition: def.h:62
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2762
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:437
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16646
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17985
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:16430
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15495
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17068
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5837
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:12746
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17730
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17515
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:715
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16014
SCIP_Bool divingobjchg
Definition: struct_lp.h:366
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17621
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:8041
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:448
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:16749
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:10118
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:16636
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11422
#define MIN(x, y)
Definition: def.h:209
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3355
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16684
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17201
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:8334
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:17191
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10876
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17935
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13257
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17078
int closestvlbidx
Definition: struct_var.h:266
#define EPSLE(x, y, eps)
Definition: def.h:177
int nuses
Definition: struct_var.h:256
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15595
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:10662
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:10915
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
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:17057
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:8447
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:13398
datastructures for problem statistics
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17111
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:17667
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12253
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:14660
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:9214
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:12668
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15881
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2245
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18052
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:15937
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:11948
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:17763
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:9495
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15993
#define SCIP_REAL_MAX
Definition: def.h:151
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:13744
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:152
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:17638
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:7222
#define MAX(x, y)
Definition: def.h:208
#define SCIP_DEFAULT_INFINITY
Definition: def.h:155
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:434
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:5261
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8354
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16676
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:17975
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:14334
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11471
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13191
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:16805
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:8986
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:16696
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:16848
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8933
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:9115
#define SCIP_Real
Definition: def.h:150
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:15172
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11757
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18005
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:16816
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:12041
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14097
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17808
#define SCIP_INVALID
Definition: def.h:170
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:16739
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11677
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:17589
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:135
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17455
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18017
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6672
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13537
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17026
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:15736
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:8824
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16894
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8202
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:6428
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:16996
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:17409
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:8395
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15867
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6238
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16871
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6498
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:433
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17419
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:17965
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:17850
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:2874
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13973
SCIP_HISTORY * history
Definition: struct_var.h:244
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16832
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15350
int nrootintfixingsrun
Definition: struct_stat.h:208
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12126
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
#define SCIP_CALL_ABORT(x)
Definition: def.h:330
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17795
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:17046
#define SCIP_ALLOC(x)
Definition: def.h:362
#define SCIPABORT()
Definition: def.h:323
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16920
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:8136
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8454
unsigned int applied
Definition: struct_var.h:94
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16950
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:10838
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:439
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5873
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16759
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16702
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:5696
SCIP_Real left
Definition: struct_var.h:44
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8706
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:180
#define ABS(x)
Definition: def.h:204
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:11232
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:14165
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17016
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:14469
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:16884
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:16986
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17955
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10898