Scippy

SCIP

Solving Constraint Integer Programs

var.c
Go to the documentation of this file.
1 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
2 /* */
3 /* This file is part of the program and library */
4 /* SCIP --- Solving Constraint Integer Programs */
5 /* */
6 /* Copyright (C) 2002-2019 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scip.zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @brief methods for problem variables
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Marc Pfetsch
23  * @author Michael Winkler
24  * @author Kati Wolter
25  * @author Stefan Vigerske
26  *
27  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
28  * corresponding linear constraint if it exists. This seems to require some work, since the linear
29  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
30  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
31  * changed. This has to be done with care in order to not loose the performance gains of
32  * multi-aggregation.
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include "scip/cons.h"
38 #include "scip/event.h"
39 #include "scip/history.h"
40 #include "scip/implics.h"
41 #include "scip/lp.h"
42 #include "scip/primal.h"
43 #include "scip/prob.h"
44 #include "scip/pub_cons.h"
45 #include "scip/pub_history.h"
46 #include "scip/pub_implics.h"
47 #include "scip/pub_lp.h"
48 #include "scip/pub_message.h"
49 #include "scip/pub_misc.h"
50 #include "scip/pub_misc_sort.h"
51 #include "scip/pub_prop.h"
52 #include "scip/pub_var.h"
53 #include "scip/relax.h"
54 #include "scip/set.h"
55 #include "scip/sol.h"
56 #include "scip/stat.h"
57 #include "scip/struct_event.h"
58 #include "scip/struct_lp.h"
59 #include "scip/struct_prob.h"
60 #include "scip/struct_set.h"
61 #include "scip/struct_stat.h"
62 #include "scip/struct_var.h"
63 #include "scip/tree.h"
64 #include "scip/var.h"
65 #include <string.h>
66 
67 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
68  * in implication graph */
69 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
70 
71 /*
72  * hole, holelist, and domain methods
73  */
74 
75 /** creates a new holelist element */
76 static
78  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
79  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
80  SCIP_SET* set, /**< global SCIP settings */
81  SCIP_Real left, /**< left bound of open interval in new hole */
82  SCIP_Real right /**< right bound of open interval in new hole */
83  )
84 {
85  assert(holelist != NULL);
86  assert(blkmem != NULL);
87  assert(SCIPsetIsLT(set, left, right));
88 
89  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
90 
91  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
92  (*holelist)->hole.left = left;
93  (*holelist)->hole.right = right;
94  (*holelist)->next = NULL;
95 
96  return SCIP_OKAY;
97 }
98 
99 /** frees all elements in the holelist */
100 static
101 void holelistFree(
102  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
103  BMS_BLKMEM* blkmem /**< block memory for target holelist */
104  )
105 {
106  assert(holelist != NULL);
107  assert(blkmem != NULL);
108 
109  while( *holelist != NULL )
110  {
111  SCIP_HOLELIST* next;
112 
113  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
114  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
115 
116  next = (*holelist)->next;
117  BMSfreeBlockMemory(blkmem, holelist);
118  assert(*holelist == NULL);
119 
120  *holelist = next;
121  }
122  assert(*holelist == NULL);
123 }
124 
125 /** duplicates a list of holes */
126 static
128  SCIP_HOLELIST** target, /**< pointer to target holelist */
129  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
130  SCIP_SET* set, /**< global SCIP settings */
131  SCIP_HOLELIST* source /**< holelist to duplicate */
132  )
133 {
134  assert(target != NULL);
135 
136  while( source != NULL )
137  {
138  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
139  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
140  source = source->next;
141  target = &(*target)->next;
142  }
143 
144  return SCIP_OKAY;
145 }
146 
147 /** adds a hole to the domain */
148 static
150  SCIP_DOM* dom, /**< domain to add hole to */
151  BMS_BLKMEM* blkmem, /**< block memory */
152  SCIP_SET* set, /**< global SCIP settings */
153  SCIP_Real left, /**< left bound of open interval in new hole */
154  SCIP_Real right, /**< right bound of open interval in new hole */
155  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
156  )
157 {
158  SCIP_HOLELIST** insertpos;
159  SCIP_HOLELIST* next;
160 
161  assert(dom != NULL);
162  assert(added != NULL);
163 
164  /* search for the position of the new hole */
165  insertpos = &dom->holelist;
166  while( *insertpos != NULL && (*insertpos)->hole.left < left )
167  insertpos = &(*insertpos)->next;
168 
169  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
170  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
171  {
172  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
173  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
174  *added = FALSE;
175  return SCIP_OKAY;
176  }
177 
178  /* add hole */
179  *added = TRUE;
180 
181  next = *insertpos;
182  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
183  (*insertpos)->next = next;
184 
185  return SCIP_OKAY;
186 }
187 
188 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
189 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
190  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
191  * merge */
192 static
193 void domMerge(
194  SCIP_DOM* dom, /**< domain to merge */
195  BMS_BLKMEM* blkmem, /**< block memory */
196  SCIP_SET* set, /**< global SCIP settings */
197  SCIP_Real* newlb, /**< pointer to store new lower bound */
198  SCIP_Real* newub /**< pointer to store new upper bound */
199  )
200 {
201  SCIP_HOLELIST** holelistptr;
202  SCIP_HOLELIST** lastnextptr;
203  SCIP_Real* lastrightptr;
204 
205  assert(dom != NULL);
206  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
207 
208 #ifndef NDEBUG
209  {
210  /* check if the holelist is sorted w.r.t. to the left interval bounds */
211  SCIP_Real lastleft;
212 
213  holelistptr = &dom->holelist;
214 
215  lastleft = -SCIPsetInfinity(set);
216 
217  while( *holelistptr != NULL )
218  {
219  if( (*holelistptr)->next != NULL )
220  {
221  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
222  lastleft = (*holelistptr)->hole.left;
223  }
224 
225  holelistptr = &(*holelistptr)->next;
226  }
227  }
228 #endif
229 
230  SCIPsetDebugMsg(set, "merge hole list\n");
231 
232  holelistptr = &dom->holelist;
233  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
234  lastnextptr = holelistptr;
235 
236  while( *holelistptr != NULL )
237  {
238  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
239 
240  /* check that the hole is not empty */
241  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
242 
243  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
244  {
245  /* the remaining holes start behind the upper bound: remove them */
246  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
247  holelistFree(holelistptr, blkmem);
248  assert(*holelistptr == NULL);
249 
250  /* unlink this hole from the previous hole */
251  *lastnextptr = NULL;
252  }
253  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
254  {
255  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
256  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
257 
258  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
259 
260  /* adjust upper bound */
261  dom->ub = (*holelistptr)->hole.left;
262 
263  if(newub != NULL )
264  *newub = (*holelistptr)->hole.left;
265 
266  /* remove remaining hole list */
267  holelistFree(holelistptr, blkmem);
268  assert(*holelistptr == NULL);
269 
270  /* unlink this hole from the previous hole */
271  *lastnextptr = NULL;
272  }
273  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
274  {
275  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
276  * the last hole, delete this hole */
277  SCIP_HOLELIST* nextholelist;
278 
279  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
280  {
281  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
282  * the lower bound */
283  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
284  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
285 
286  /* adjust lower bound */
287  dom->lb = *lastrightptr;
288 
289  if(newlb != NULL )
290  *newlb = *lastrightptr;
291  }
292  else
293  {
294  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
295  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
296  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
297  }
298  nextholelist = (*holelistptr)->next;
299  (*holelistptr)->next = NULL;
300  holelistFree(holelistptr, blkmem);
301 
302  /* connect the linked list after removing the hole */
303  *lastnextptr = nextholelist;
304 
305  /* get next hole */
306  *holelistptr = nextholelist;
307  }
308  else
309  {
310  /* the holes do not overlap: update lastholelist and lastrightptr */
311  lastrightptr = &(*holelistptr)->hole.right;
312  lastnextptr = &(*holelistptr)->next;
313 
314  /* get next hole */
315  holelistptr = &(*holelistptr)->next;
316  }
317  }
318 
319 #ifndef NDEBUG
320  {
321  /* check that holes are merged */
322  SCIP_Real lastright;
323 
324  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
325  holelistptr = &dom->holelist;
326 
327  while( *holelistptr != NULL )
328  {
329  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
330  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
331 
332  /* check the hole property (check that the hole is not empty) */
333  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
334  lastright = (*holelistptr)->hole.right;
335 
336  /* get next hole */
337  holelistptr = &(*holelistptr)->next;
338  }
339 
340  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
341  assert( SCIPsetIsLE(set, lastright, dom->ub) );
342  }
343 #endif
344 }
345 
346 /*
347  * domain change methods
348  */
349 
350 /** ensures, that bound change info array for lower bound changes can store at least num entries */
351 static
353  SCIP_VAR* var, /**< problem variable */
354  BMS_BLKMEM* blkmem, /**< block memory */
355  SCIP_SET* set, /**< global SCIP settings */
356  int num /**< minimum number of entries to store */
357  )
358 {
359  assert(var != NULL);
360  assert(var->nlbchginfos <= var->lbchginfossize);
361  assert(SCIPvarIsTransformed(var));
362 
363  if( num > var->lbchginfossize )
364  {
365  int newsize;
366 
367  newsize = SCIPsetCalcMemGrowSize(set, num);
368  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
369  var->lbchginfossize = newsize;
370  }
371  assert(num <= var->lbchginfossize);
372 
373  return SCIP_OKAY;
374 }
375 
376 /** ensures, that bound change info array for upper bound changes can store at least num entries */
377 static
379  SCIP_VAR* var, /**< problem variable */
380  BMS_BLKMEM* blkmem, /**< block memory */
381  SCIP_SET* set, /**< global SCIP settings */
382  int num /**< minimum number of entries to store */
383  )
384 {
385  assert(var != NULL);
386  assert(var->nubchginfos <= var->ubchginfossize);
387  assert(SCIPvarIsTransformed(var));
388 
389  if( num > var->ubchginfossize )
390  {
391  int newsize;
392 
393  newsize = SCIPsetCalcMemGrowSize(set, num);
394  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
395  var->ubchginfossize = newsize;
396  }
397  assert(num <= var->ubchginfossize);
398 
399  return SCIP_OKAY;
400 }
401 
402 /** adds domain change info to the variable's lower bound change info array */
403 static
405  SCIP_VAR* var, /**< problem variable */
406  BMS_BLKMEM* blkmem, /**< block memory */
407  SCIP_SET* set, /**< global SCIP settings */
408  SCIP_Real oldbound, /**< old value for bound */
409  SCIP_Real newbound, /**< new value for bound */
410  int depth, /**< depth in the tree, where the bound change takes place */
411  int pos, /**< position of the bound change in its bound change array */
412  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
413  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
414  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
415  int inferinfo, /**< user information for inference to help resolving the conflict */
416  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
417  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
418  )
419 {
420  assert(var != NULL);
421  assert(SCIPsetIsLT(set, oldbound, newbound));
422  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
423  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
424  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
425  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
426  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
427  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
428  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
429 
430  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
431  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
432  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
433  oldbound, newbound);
434 
435  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
436  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
437  var->lbchginfos[var->nlbchginfos].newbound = newbound;
438  var->lbchginfos[var->nlbchginfos].var = var;
439  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
440  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
441  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
442  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
443  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
444  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
445  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
446  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
447  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
448 
449  /**@note The "pos" data member of the bound change info has a size of 27 bits */
450  assert(var->nlbchginfos < 1 << 27);
451 
452  switch( boundchgtype )
453  {
455  break;
457  assert(infercons != NULL);
458  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
459  break;
461  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
462  break;
463  default:
464  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
465  return SCIP_INVALIDDATA;
466  }
467 
468  var->nlbchginfos++;
469 
470  assert(var->nlbchginfos < 2
472  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
473 
474  return SCIP_OKAY;
475 }
476 
477 /** adds domain change info to the variable's upper bound change info array */
478 static
480  SCIP_VAR* var, /**< problem variable */
481  BMS_BLKMEM* blkmem, /**< block memory */
482  SCIP_SET* set, /**< global SCIP settings */
483  SCIP_Real oldbound, /**< old value for bound */
484  SCIP_Real newbound, /**< new value for bound */
485  int depth, /**< depth in the tree, where the bound change takes place */
486  int pos, /**< position of the bound change in its bound change array */
487  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
488  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
489  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
490  int inferinfo, /**< user information for inference to help resolving the conflict */
491  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
492  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
493  )
494 {
495  assert(var != NULL);
496  assert(SCIPsetIsGT(set, oldbound, newbound));
497  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
498  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
499  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
500  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
501  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
502  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
503  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
504 
505  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
506  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
507  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
508  oldbound, newbound);
509 
510  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
511  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
512  var->ubchginfos[var->nubchginfos].newbound = newbound;
513  var->ubchginfos[var->nubchginfos].var = var;
514  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
515  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
516  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
517  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
518  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
519  var->ubchginfos[var->nubchginfos].redundant = FALSE;
520  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
521  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
522  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
523 
524  /**@note The "pos" data member of the bound change info has a size of 27 bits */
525  assert(var->nubchginfos < 1 << 27);
526 
527  switch( boundchgtype )
528  {
530  break;
532  assert(infercons != NULL);
533  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
534  break;
536  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
537  break;
538  default:
539  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
540  return SCIP_INVALIDDATA;
541  }
542 
543  var->nubchginfos++;
544 
545  assert(var->nubchginfos < 2
547  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
548 
549  return SCIP_OKAY;
550 }
551 
552 /** applies single bound change */
554  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
555  BMS_BLKMEM* blkmem, /**< block memory */
556  SCIP_SET* set, /**< global SCIP settings */
557  SCIP_STAT* stat, /**< problem statistics */
558  SCIP_LP* lp, /**< current LP data */
559  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
560  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
561  int depth, /**< depth in the tree, where the bound change takes place */
562  int pos, /**< position of the bound change in its bound change array */
563  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
564  )
565 {
566  SCIP_VAR* var;
567 
568  assert(boundchg != NULL);
569  assert(stat != NULL);
570  assert(depth > 0);
571  assert(pos >= 0);
572  assert(cutoff != NULL);
573 
574  *cutoff = FALSE;
575 
576  /* ignore redundant bound changes */
577  if( boundchg->redundant )
578  return SCIP_OKAY;
579 
580  var = boundchg->var;
581  assert(var != NULL);
583  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
584 
585  /* apply bound change */
586  switch( boundchg->boundtype )
587  {
589  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
590  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
591  {
592  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
593  {
594  /* add the bound change info to the variable's bound change info array */
595  switch( boundchg->boundchgtype )
596  {
598  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
599  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
600  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
602  stat->lastbranchvar = var;
604  stat->lastbranchvalue = boundchg->newbound;
605  break;
606 
608  assert(boundchg->data.inferencedata.reason.cons != NULL);
609  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
610  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
611  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
612  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
613  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
614  boundchg->data.inferencedata.info,
616  break;
617 
619  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
620  boundchg->data.inferencedata.reason.prop != NULL
621  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
622  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
623  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
624  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
625  boundchg->data.inferencedata.info,
627  break;
628 
629  default:
630  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
631  return SCIP_INVALIDDATA;
632  }
633 
634  /* change local bound of variable */
635  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
636  }
637  else
638  {
639  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
640  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
641  *cutoff = TRUE;
642  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
643  }
644  }
645  else
646  {
647  /* mark bound change to be inactive */
648  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
649  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
650  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
651  boundchg->redundant = TRUE;
652  }
653  break;
654 
656  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
657  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
658  {
659  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
660  {
661  /* add the bound change info to the variable's bound change info array */
662  switch( boundchg->boundchgtype )
663  {
665  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
666  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
667  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
669  stat->lastbranchvar = var;
671  stat->lastbranchvalue = boundchg->newbound;
672  break;
673 
675  assert(boundchg->data.inferencedata.reason.cons != NULL);
676  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
677  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
678  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
679  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
680  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
681  boundchg->data.inferencedata.info,
683  break;
684 
686  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
687  boundchg->data.inferencedata.reason.prop != NULL
688  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
689  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
690  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
691  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
692  boundchg->data.inferencedata.info,
694  break;
695 
696  default:
697  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
698  return SCIP_INVALIDDATA;
699  }
700 
701  /* change local bound of variable */
702  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
703  }
704  else
705  {
706  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
707  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
708  *cutoff = TRUE;
709  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
710  }
711  }
712  else
713  {
714  /* mark bound change to be inactive */
715  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
716  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
717  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
718  boundchg->redundant = TRUE;
719  }
720  break;
721 
722  default:
723  SCIPerrorMessage("unknown bound type\n");
724  return SCIP_INVALIDDATA;
725  }
726 
727  /* update the branching and inference history */
728  if( !boundchg->applied && !boundchg->redundant )
729  {
730  assert(var == boundchg->var);
731 
733  {
734  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
737  }
738  else if( stat->lastbranchvar != NULL )
739  {
740  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
741  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
742  }
743  boundchg->applied = TRUE;
744  }
745 
746  return SCIP_OKAY;
747 }
748 
749 /** undoes single bound change */
751  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
752  BMS_BLKMEM* blkmem, /**< block memory */
753  SCIP_SET* set, /**< global SCIP settings */
754  SCIP_STAT* stat, /**< problem statistics */
755  SCIP_LP* lp, /**< current LP data */
756  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
757  SCIP_EVENTQUEUE* eventqueue /**< event queue */
758  )
759 {
760  SCIP_VAR* var;
761 
762  assert(boundchg != NULL);
763  assert(stat != NULL);
764 
765  /* ignore redundant bound changes */
766  if( boundchg->redundant )
767  return SCIP_OKAY;
768 
769  var = boundchg->var;
770  assert(var != NULL);
772 
773  /* undo bound change: apply the previous bound change of variable */
774  switch( boundchg->boundtype )
775  {
777  var->nlbchginfos--;
778  assert(var->nlbchginfos >= 0);
779  assert(var->lbchginfos != NULL);
780  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
781  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
782 
783  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
784  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
787 
788  /* reinstall the previous local bound */
789  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
790  var->lbchginfos[var->nlbchginfos].oldbound) );
791 
792  /* in case all bound changes are removed the local bound should match the global bound */
793  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
794 
795  break;
796 
798  var->nubchginfos--;
799  assert(var->nubchginfos >= 0);
800  assert(var->ubchginfos != NULL);
801  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
802  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
803 
804  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
805  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
808 
809  /* reinstall the previous local bound */
810  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
811  var->ubchginfos[var->nubchginfos].oldbound) );
812 
813  /* in case all bound changes are removed the local bound should match the global bound */
814  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
815 
816  break;
817 
818  default:
819  SCIPerrorMessage("unknown bound type\n");
820  return SCIP_INVALIDDATA;
821  }
822 
823  /* update last branching variable */
825  {
826  stat->lastbranchvar = NULL;
828  }
829 
830  return SCIP_OKAY;
831 }
832 
833 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
834 static
836  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
837  BMS_BLKMEM* blkmem, /**< block memory */
838  SCIP_SET* set, /**< global SCIP settings */
839  SCIP_STAT* stat, /**< problem statistics */
840  SCIP_LP* lp, /**< current LP data */
841  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
842  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
843  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
844  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
845  )
846 {
847  SCIP_VAR* var;
848  SCIP_Real newbound;
849  SCIP_BOUNDTYPE boundtype;
850 
851  assert(boundchg != NULL);
852  assert(cutoff != NULL);
853 
854  *cutoff = FALSE;
855 
856  /* ignore redundant bound changes */
857  if( boundchg->redundant )
858  return SCIP_OKAY;
859 
860  var = SCIPboundchgGetVar(boundchg);
861  newbound = SCIPboundchgGetNewbound(boundchg);
862  boundtype = SCIPboundchgGetBoundtype(boundchg);
863 
864  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
865  * after that bound change was applied
866  *
867  * @note a global bound change is not captured by the redundant member of the bound change data structure
868  */
869  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
870  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
871  {
872  return SCIP_OKAY;
873  }
874 
875  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
877  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
878 
879  /* check for cutoff */
880  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
881  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
882  {
883  *cutoff = TRUE;
884  return SCIP_OKAY;
885  }
886 
887  /* apply bound change */
888  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
889 
890  return SCIP_OKAY;
891 }
892 
893 /** captures branching and inference data of bound change */
894 static
896  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
897  )
898 {
899  assert(boundchg != NULL);
900 
901  /* capture variable associated with the bound change */
902  assert(boundchg->var != NULL);
903  SCIPvarCapture(boundchg->var);
904 
905  switch( boundchg->boundchgtype )
906  {
909  break;
910 
912  assert(boundchg->data.inferencedata.var != NULL);
913  assert(boundchg->data.inferencedata.reason.cons != NULL);
914  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
915  break;
916 
917  default:
918  SCIPerrorMessage("invalid bound change type\n");
919  return SCIP_INVALIDDATA;
920  }
921 
922  return SCIP_OKAY;
923 }
924 
925 /** releases branching and inference data of bound change */
926 static
928  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
929  BMS_BLKMEM* blkmem, /**< block memory */
930  SCIP_SET* set, /**< global SCIP settings */
931  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
932  SCIP_LP* lp /**< current LP data */
933 
934  )
935 {
936  assert(boundchg != NULL);
937 
938  switch( boundchg->boundchgtype )
939  {
942  break;
943 
945  assert(boundchg->data.inferencedata.var != NULL);
946  assert(boundchg->data.inferencedata.reason.cons != NULL);
947  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
948  break;
949 
950  default:
951  SCIPerrorMessage("invalid bound change type\n");
952  return SCIP_INVALIDDATA;
953  }
954 
955  /* release variable */
956  assert(boundchg->var != NULL);
957  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
958 
959  return SCIP_OKAY;
960 }
961 
962 /** creates empty domain change data with dynamic arrays */
963 static
965  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
966  BMS_BLKMEM* blkmem /**< block memory */
967  )
968 {
969  assert(domchg != NULL);
970  assert(blkmem != NULL);
971 
972  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
973  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
974  (*domchg)->domchgdyn.nboundchgs = 0;
975  (*domchg)->domchgdyn.boundchgs = NULL;
976  (*domchg)->domchgdyn.nholechgs = 0;
977  (*domchg)->domchgdyn.holechgs = NULL;
978  (*domchg)->domchgdyn.boundchgssize = 0;
979  (*domchg)->domchgdyn.holechgssize = 0;
980 
981  return SCIP_OKAY;
982 }
983 
984 /** frees domain change data */
986  SCIP_DOMCHG** domchg, /**< pointer to domain change */
987  BMS_BLKMEM* blkmem, /**< block memory */
988  SCIP_SET* set, /**< global SCIP settings */
989  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
990  SCIP_LP* lp /**< current LP data */
991  )
992 {
993  assert(domchg != NULL);
994  assert(blkmem != NULL);
995 
996  if( *domchg != NULL )
997  {
998  int i;
999 
1000  /* release variables, branching and inference data associated with the bound changes */
1001  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1002  {
1003  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1004  }
1005 
1006  /* free memory for bound and hole changes */
1007  switch( (*domchg)->domchgdyn.domchgtype )
1008  {
1009  case SCIP_DOMCHGTYPE_BOUND:
1010  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1011  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1012  break;
1013  case SCIP_DOMCHGTYPE_BOTH:
1014  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1015  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1016  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1017  break;
1019  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1020  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1021  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1022  break;
1023  default:
1024  SCIPerrorMessage("invalid domain change type\n");
1025  return SCIP_INVALIDDATA;
1026  }
1027  }
1028 
1029  return SCIP_OKAY;
1030 }
1031 
1032 /** converts a static domain change data into a dynamic one */
1033 static
1035  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1036  BMS_BLKMEM* blkmem /**< block memory */
1037  )
1038 {
1039  assert(domchg != NULL);
1040  assert(blkmem != NULL);
1041 
1042  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1043 
1044  if( *domchg == NULL )
1045  {
1046  SCIP_CALL( domchgCreate(domchg, blkmem) );
1047  }
1048  else
1049  {
1050  switch( (*domchg)->domchgdyn.domchgtype )
1051  {
1052  case SCIP_DOMCHGTYPE_BOUND:
1053  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1054  (*domchg)->domchgdyn.nholechgs = 0;
1055  (*domchg)->domchgdyn.holechgs = NULL;
1056  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1057  (*domchg)->domchgdyn.holechgssize = 0;
1058  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1059  break;
1060  case SCIP_DOMCHGTYPE_BOTH:
1061  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1062  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1063  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1064  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1065  break;
1067  break;
1068  default:
1069  SCIPerrorMessage("invalid domain change type\n");
1070  return SCIP_INVALIDDATA;
1071  }
1072  }
1073 #ifndef NDEBUG
1074  {
1075  int i;
1076  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1077  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1078  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1079  }
1080 #endif
1081 
1082  return SCIP_OKAY;
1083 }
1084 
1085 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1087  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1088  BMS_BLKMEM* blkmem, /**< block memory */
1089  SCIP_SET* set, /**< global SCIP settings */
1090  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1091  SCIP_LP* lp /**< current LP data */
1092  )
1093 {
1094  assert(domchg != NULL);
1095  assert(blkmem != NULL);
1096 
1097  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1098 
1099  if( *domchg != NULL )
1100  {
1101  switch( (*domchg)->domchgdyn.domchgtype )
1102  {
1103  case SCIP_DOMCHGTYPE_BOUND:
1104  if( (*domchg)->domchgbound.nboundchgs == 0 )
1105  {
1106  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1107  }
1108  break;
1109  case SCIP_DOMCHGTYPE_BOTH:
1110  if( (*domchg)->domchgboth.nholechgs == 0 )
1111  {
1112  if( (*domchg)->domchgbound.nboundchgs == 0 )
1113  {
1114  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1115  }
1116  else
1117  {
1118  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1119  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1120  }
1121  }
1122  break;
1124  if( (*domchg)->domchgboth.nholechgs == 0 )
1125  {
1126  if( (*domchg)->domchgbound.nboundchgs == 0 )
1127  {
1128  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1129  }
1130  else
1131  {
1132  /* shrink dynamic size arrays to their minimal sizes */
1133  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1134  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1135  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1136 
1137  /* convert into static domain change */
1138  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1139  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1140  }
1141  }
1142  else
1143  {
1144  /* shrink dynamic size arrays to their minimal sizes */
1145  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1146  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1147  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1148  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1149 
1150  /* convert into static domain change */
1151  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1152  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1153  }
1154  break;
1155  default:
1156  SCIPerrorMessage("invalid domain change type\n");
1157  return SCIP_INVALIDDATA;
1158  }
1159 #ifndef NDEBUG
1160  if( *domchg != NULL )
1161  {
1162  int i;
1163  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1164  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1165  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1166  }
1167 #endif
1168  }
1169 
1170  return SCIP_OKAY;
1171 }
1172 
1173 /** ensures, that boundchgs array can store at least num entries */
1174 static
1176  SCIP_DOMCHG* domchg, /**< domain change data structure */
1177  BMS_BLKMEM* blkmem, /**< block memory */
1178  SCIP_SET* set, /**< global SCIP settings */
1179  int num /**< minimum number of entries to store */
1180  )
1181 {
1182  assert(domchg != NULL);
1183  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1184 
1185  if( num > domchg->domchgdyn.boundchgssize )
1186  {
1187  int newsize;
1188 
1189  newsize = SCIPsetCalcMemGrowSize(set, num);
1190  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1191  domchg->domchgdyn.boundchgssize = newsize;
1192  }
1193  assert(num <= domchg->domchgdyn.boundchgssize);
1194 
1195  return SCIP_OKAY;
1196 }
1197 
1198 /** ensures, that holechgs array can store at least num additional entries */
1199 static
1201  SCIP_DOMCHG* domchg, /**< domain change data structure */
1202  BMS_BLKMEM* blkmem, /**< block memory */
1203  SCIP_SET* set, /**< global SCIP settings */
1204  int num /**< minimum number of additional entries to store */
1205  )
1206 {
1207  assert(domchg != NULL);
1208  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1209 
1210  if( num > domchg->domchgdyn.holechgssize )
1211  {
1212  int newsize;
1213 
1214  newsize = SCIPsetCalcMemGrowSize(set, num);
1215  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1216  domchg->domchgdyn.holechgssize = newsize;
1217  }
1218  assert(num <= domchg->domchgdyn.holechgssize);
1219 
1220  return SCIP_OKAY;
1221 }
1222 
1223 /** applies domain change */
1225  SCIP_DOMCHG* domchg, /**< domain change to apply */
1226  BMS_BLKMEM* blkmem, /**< block memory */
1227  SCIP_SET* set, /**< global SCIP settings */
1228  SCIP_STAT* stat, /**< problem statistics */
1229  SCIP_LP* lp, /**< current LP data */
1230  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1231  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1232  int depth, /**< depth in the tree, where the domain change takes place */
1233  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1234  )
1235 {
1236  int i;
1237 
1238  assert(cutoff != NULL);
1239 
1240  *cutoff = FALSE;
1241 
1242  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1243 
1244  if( domchg == NULL )
1245  return SCIP_OKAY;
1246 
1247  /* apply bound changes */
1248  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1249  {
1250  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1251  branchcand, eventqueue, depth, i, cutoff) );
1252  if( *cutoff )
1253  break;
1254  }
1255  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1256 
1257  /* mark all bound changes after a cutoff redundant */
1258  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1259  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1260 
1261  /* apply holelist changes */
1262  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1263  {
1264  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1265  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1266  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1267  }
1268 
1269  return SCIP_OKAY;
1270 }
1271 
1272 /** undoes domain change */
1274  SCIP_DOMCHG* domchg, /**< domain change to remove */
1275  BMS_BLKMEM* blkmem, /**< block memory */
1276  SCIP_SET* set, /**< global SCIP settings */
1277  SCIP_STAT* stat, /**< problem statistics */
1278  SCIP_LP* lp, /**< current LP data */
1279  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1280  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1281  )
1282 {
1283  int i;
1284 
1285  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1286  if( domchg == NULL )
1287  return SCIP_OKAY;
1288 
1289  /* undo holelist changes */
1290  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1291  {
1292  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1293  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1294  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1295  }
1296 
1297  /* undo bound changes */
1298  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1299  {
1300  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1301  }
1302  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1303 
1304  return SCIP_OKAY;
1305 }
1306 
1307 /** applies domain change to the global problem */
1309  SCIP_DOMCHG* domchg, /**< domain change to apply */
1310  BMS_BLKMEM* blkmem, /**< block memory */
1311  SCIP_SET* set, /**< global SCIP settings */
1312  SCIP_STAT* stat, /**< problem statistics */
1313  SCIP_LP* lp, /**< current LP data */
1314  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1315  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1316  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1317  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1318  )
1319 {
1320  int i;
1321 
1322  assert(cutoff != NULL);
1323 
1324  *cutoff = FALSE;
1325 
1326  if( domchg == NULL )
1327  return SCIP_OKAY;
1328 
1329  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1330 
1331  /* apply bound changes */
1332  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1333  {
1334  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1335  branchcand, eventqueue, cliquetable, cutoff) );
1336  if( *cutoff )
1337  break;
1338  }
1339  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1340 
1341  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1342 
1343  return SCIP_OKAY;
1344 }
1345 
1346 /** adds bound change to domain changes */
1348  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1349  BMS_BLKMEM* blkmem, /**< block memory */
1350  SCIP_SET* set, /**< global SCIP settings */
1351  SCIP_VAR* var, /**< variable to change the bounds for */
1352  SCIP_Real newbound, /**< new value for bound */
1353  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1354  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1355  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1356  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1357  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1358  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1359  int inferinfo, /**< user information for inference to help resolving the conflict */
1360  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1361  )
1362 {
1363  SCIP_BOUNDCHG* boundchg;
1364 
1365  assert(domchg != NULL);
1366  assert(var != NULL);
1368  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1369  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1370  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1371  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1372  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1373 
1374  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1375  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1376  newbound, var->name, (void*)domchg, (void*)*domchg);
1377 
1378  /* if domain change data doesn't exist, create it;
1379  * if domain change is static, convert it into dynamic change
1380  */
1381  if( *domchg == NULL )
1382  {
1383  SCIP_CALL( domchgCreate(domchg, blkmem) );
1384  }
1385  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1386  {
1387  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1388  }
1389  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1390 
1391  /* get memory for additional bound change */
1392  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1393 
1394  /* fill in the bound change data */
1395  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1396  boundchg->var = var;
1397  switch( boundchgtype )
1398  {
1400  boundchg->data.branchingdata.lpsolval = lpsolval;
1401  break;
1403  assert(infercons != NULL);
1404  boundchg->data.inferencedata.var = infervar;
1405  boundchg->data.inferencedata.reason.cons = infercons;
1406  boundchg->data.inferencedata.info = inferinfo;
1407  break;
1409  boundchg->data.inferencedata.var = infervar;
1410  boundchg->data.inferencedata.reason.prop = inferprop;
1411  boundchg->data.inferencedata.info = inferinfo;
1412  break;
1413  default:
1414  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1415  return SCIP_INVALIDDATA;
1416  }
1417 
1418  boundchg->newbound = newbound;
1419  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1420  boundchg->boundtype = boundtype; /*lint !e641*/
1421  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1422  boundchg->applied = FALSE;
1423  boundchg->redundant = FALSE;
1424  (*domchg)->domchgdyn.nboundchgs++;
1425 
1426  /* capture branching and inference data associated with the bound changes */
1427  SCIP_CALL( boundchgCaptureData(boundchg) );
1428 
1429 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1430 #ifdef SCIP_MORE_DEBUG
1431  {
1432  int i;
1433  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1434  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1435  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1436  }
1437 #endif
1438 #endif
1439 
1440  return SCIP_OKAY;
1441 }
1442 
1443 /** adds hole change to domain changes */
1445  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1446  BMS_BLKMEM* blkmem, /**< block memory */
1447  SCIP_SET* set, /**< global SCIP settings */
1448  SCIP_HOLELIST** ptr, /**< changed list pointer */
1449  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1450  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1451  )
1452 {
1453  SCIP_HOLECHG* holechg;
1454 
1455  assert(domchg != NULL);
1456  assert(ptr != NULL);
1457 
1458  /* if domain change data doesn't exist, create it;
1459  * if domain change is static, convert it into dynamic change
1460  */
1461  if( *domchg == NULL )
1462  {
1463  SCIP_CALL( domchgCreate(domchg, blkmem) );
1464  }
1465  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1466  {
1467  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1468  }
1469  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1470 
1471  /* get memory for additional hole change */
1472  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1473 
1474  /* fill in the hole change data */
1475  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1476  holechg->ptr = ptr;
1477  holechg->newlist = newlist;
1478  holechg->oldlist = oldlist;
1479  (*domchg)->domchgdyn.nholechgs++;
1480 
1481  return SCIP_OKAY;
1482 }
1483 
1484 
1485 
1486 
1487 /*
1488  * methods for variables
1489  */
1490 
1491 /** returns adjusted lower bound value, which is rounded for integral variable types */
1492 static
1494  SCIP_SET* set, /**< global SCIP settings */
1495  SCIP_VARTYPE vartype, /**< type of variable */
1496  SCIP_Real lb /**< lower bound to adjust */
1497  )
1498 {
1499  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1500  return -SCIPsetInfinity(set);
1501  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1502  return SCIPsetInfinity(set);
1503  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1504  return SCIPsetFeasCeil(set, lb);
1505  else if( SCIPsetIsZero(set, lb) )
1506  return 0.0;
1507  else
1508  return lb;
1509 }
1510 
1511 /** returns adjusted upper bound value, which is rounded for integral variable types */
1512 static
1514  SCIP_SET* set, /**< global SCIP settings */
1515  SCIP_VARTYPE vartype, /**< type of variable */
1516  SCIP_Real ub /**< upper bound to adjust */
1517  )
1518 {
1519  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1520  return SCIPsetInfinity(set);
1521  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1522  return -SCIPsetInfinity(set);
1523  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1524  return SCIPsetFeasFloor(set, ub);
1525  else if( SCIPsetIsZero(set, ub) )
1526  return 0.0;
1527  else
1528  return ub;
1529 }
1530 
1531 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1532  * bounds arrays, and optionally removes them also from the variable itself
1533  */
1535  SCIP_VAR* var, /**< problem variable */
1536  BMS_BLKMEM* blkmem, /**< block memory */
1537  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1538  SCIP_SET* set, /**< global SCIP settings */
1539  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1540  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1541  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1542  )
1543 {
1544  SCIP_Real lb;
1545  SCIP_Real ub;
1546 
1547  assert(var != NULL);
1549  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1550 
1551  lb = SCIPvarGetLbGlobal(var);
1552  ub = SCIPvarGetUbGlobal(var);
1553 
1554  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1555  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1556 
1557  /* remove implications of (fixed) binary variable */
1558  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1559  {
1560  SCIP_Bool varfixing;
1561 
1562  assert(SCIPvarIsBinary(var));
1563 
1564  varfixing = FALSE;
1565  do
1566  {
1567  SCIP_VAR** implvars;
1568  SCIP_BOUNDTYPE* impltypes;
1569  int nimpls;
1570  int i;
1571 
1572  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1573  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1574  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1575 
1576  for( i = 0; i < nimpls; i++ )
1577  {
1578  SCIP_VAR* implvar;
1579  SCIP_BOUNDTYPE impltype;
1580 
1581  implvar = implvars[i];
1582  impltype = impltypes[i];
1583  assert(implvar != var);
1584 
1585  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1586  * the following variable bound from x's variable bounds
1587  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1588  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1589  */
1590  if( impltype == SCIP_BOUNDTYPE_UPPER )
1591  {
1592  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1593  {
1594  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1595  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1596  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1597  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1598  implvar->closestvblpcount = -1;
1599  var->closestvblpcount = -1;
1600  }
1601  }
1602  else
1603  {
1604  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1605  {
1606  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1607  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1608  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1609  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1610  implvar->closestvblpcount = -1;
1611  var->closestvblpcount = -1;
1612  }
1613  }
1614  }
1615  varfixing = !varfixing;
1616  }
1617  while( varfixing == TRUE );
1618 
1619  if( removefromvar )
1620  {
1621  /* free the implications data structures */
1622  SCIPimplicsFree(&var->implics, blkmem);
1623  }
1624  }
1625 
1626  /* remove the (redundant) variable lower bounds */
1627  if( var->vlbs != NULL )
1628  {
1629  SCIP_VAR** vars;
1630  SCIP_Real* coefs;
1631  SCIP_Real* constants;
1632  int nvbds;
1633  int newnvbds;
1634  int i;
1635 
1636  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1637  vars = SCIPvboundsGetVars(var->vlbs);
1638  coefs = SCIPvboundsGetCoefs(var->vlbs);
1639  constants = SCIPvboundsGetConstants(var->vlbs);
1640 
1641  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1642  * z == ub ==> x >= b*ub + d , if b > 0
1643  * z == lb ==> x >= b*lb + d , if b < 0
1644  */
1645  newnvbds = 0;
1646  for( i = 0; i < nvbds; i++ )
1647  {
1648  SCIP_VAR* implvar;
1649  SCIP_Real coef;
1650 
1651  assert(newnvbds <= i);
1652 
1653  implvar = vars[i];
1654  assert(implvar != NULL);
1655 
1656  coef = coefs[i];
1657  assert(!SCIPsetIsZero(set, coef));
1658 
1659  /* check, if we want to remove the variable bound */
1660  if( onlyredundant )
1661  {
1662  SCIP_Real vbound;
1663 
1664  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1665  if( SCIPsetIsFeasGT(set, vbound, lb) )
1666  {
1667  /* the variable bound is not redundant: keep it */
1668  if( removefromvar )
1669  {
1670  if( newnvbds < i )
1671  {
1672  vars[newnvbds] = implvar;
1673  coefs[newnvbds] = coef;
1674  constants[newnvbds] = constants[i];
1675  }
1676  newnvbds++;
1677  }
1678  continue;
1679  }
1680  }
1681 
1682  /* remove the corresponding implication */
1683  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1684  {
1685  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1686  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1687  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1688  }
1689  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1690  {
1691  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1692  SCIPvarGetName(implvar), SCIPvarGetName(var));
1693  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1694  implvar->closestvblpcount = -1;
1695  var->closestvblpcount = -1;
1696  }
1697  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1698  {
1699  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1700  SCIPvarGetName(implvar), SCIPvarGetName(var));
1701  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1702  implvar->closestvblpcount = -1;
1703  var->closestvblpcount = -1;
1704  }
1705  }
1706 
1707  if( removefromvar )
1708  {
1709  /* update the number of variable bounds */
1710  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1711  var->closestvblpcount = -1;
1712  }
1713  }
1714 
1715  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1716  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1717  * cannot remove such variables x from z's implications.
1718  */
1719 
1720  /* remove the (redundant) variable upper bounds */
1721  if( var->vubs != NULL )
1722  {
1723  SCIP_VAR** vars;
1724  SCIP_Real* coefs;
1725  SCIP_Real* constants;
1726  int nvbds;
1727  int newnvbds;
1728  int i;
1729 
1730  nvbds = SCIPvboundsGetNVbds(var->vubs);
1731  vars = SCIPvboundsGetVars(var->vubs);
1732  coefs = SCIPvboundsGetCoefs(var->vubs);
1733  constants = SCIPvboundsGetConstants(var->vubs);
1734 
1735  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1736  * z == lb ==> x <= b*lb + d , if b > 0
1737  * z == ub ==> x <= b*ub + d , if b < 0
1738  */
1739  newnvbds = 0;
1740  for( i = 0; i < nvbds; i++ )
1741  {
1742  SCIP_VAR* implvar;
1743  SCIP_Real coef;
1744 
1745  assert(newnvbds <= i);
1746 
1747  implvar = vars[i];
1748  assert(implvar != NULL);
1749 
1750  coef = coefs[i];
1751  assert(!SCIPsetIsZero(set, coef));
1752 
1753  /* check, if we want to remove the variable bound */
1754  if( onlyredundant )
1755  {
1756  SCIP_Real vbound;
1757 
1758  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1759  if( SCIPsetIsFeasLT(set, vbound, ub) )
1760  {
1761  /* the variable bound is not redundant: keep it */
1762  if( removefromvar )
1763  {
1764  if( newnvbds < i )
1765  {
1766  vars[newnvbds] = implvar;
1767  coefs[newnvbds] = coefs[i];
1768  constants[newnvbds] = constants[i];
1769  }
1770  newnvbds++;
1771  }
1772  continue;
1773  }
1774  }
1775 
1776  /* remove the corresponding implication */
1777  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1778  {
1779  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1780  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1781  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1782  }
1783  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1784  {
1785  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1786  SCIPvarGetName(implvar), SCIPvarGetName(var));
1787  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1788  implvar->closestvblpcount = -1;
1789  var->closestvblpcount = -1;
1790  }
1791  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1792  {
1793  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1794  SCIPvarGetName(implvar), SCIPvarGetName(var));
1795  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1796  implvar->closestvblpcount = -1;
1797  var->closestvblpcount = -1;
1798  }
1799  }
1800 
1801  if( removefromvar )
1802  {
1803  /* update the number of variable bounds */
1804  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1805  var->closestvblpcount = -1;
1806  }
1807  }
1808 
1809  /* remove the variable from all cliques */
1810  if( SCIPvarIsBinary(var) )
1811  {
1812  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1813  SCIPcliquelistFree(&var->cliquelist, blkmem);
1814  }
1815 
1816  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1817  * z has no link (like in the binary case) to x
1818  */
1819 
1820  return SCIP_OKAY;
1821 }
1822 
1823 /** sets the variable name */
1824 static
1826  SCIP_VAR* var, /**< problem variable */
1827  BMS_BLKMEM* blkmem, /**< block memory */
1828  SCIP_STAT* stat, /**< problem statistics, or NULL */
1829  const char* name /**< name of variable, or NULL for automatic name creation */
1830  )
1831 {
1832  assert(blkmem != NULL);
1833  assert(var != NULL);
1834 
1835  if( name == NULL )
1836  {
1837  char s[SCIP_MAXSTRLEN];
1838 
1839  assert(stat != NULL);
1840 
1841  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1842  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1843  }
1844  else
1845  {
1846  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1847  }
1848 
1849  return SCIP_OKAY;
1850 }
1851 
1852 
1853 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1854  * with bounds zero and one is automatically converted into a binary variable
1855  */
1856 static
1858  SCIP_VAR** var, /**< pointer to variable data */
1859  BMS_BLKMEM* blkmem, /**< block memory */
1860  SCIP_SET* set, /**< global SCIP settings */
1861  SCIP_STAT* stat, /**< problem statistics */
1862  const char* name, /**< name of variable, or NULL for automatic name creation */
1863  SCIP_Real lb, /**< lower bound of variable */
1864  SCIP_Real ub, /**< upper bound of variable */
1865  SCIP_Real obj, /**< objective function value */
1866  SCIP_VARTYPE vartype, /**< type of variable */
1867  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1868  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1869  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1870  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1871  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1872  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1873  SCIP_VARDATA* vardata /**< user data for this specific variable */
1874  )
1875 {
1876  int i;
1877 
1878  assert(var != NULL);
1879  assert(blkmem != NULL);
1880  assert(stat != NULL);
1881 
1882  /* adjust bounds of variable */
1883  lb = adjustedLb(set, vartype, lb);
1884  ub = adjustedUb(set, vartype, ub);
1885 
1886  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1887  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1888  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1889  {
1890  if( vartype == SCIP_VARTYPE_INTEGER )
1891  vartype = SCIP_VARTYPE_BINARY;
1892  }
1893  else
1894  {
1895  if( vartype == SCIP_VARTYPE_BINARY )
1896  {
1897  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1898  return SCIP_INVALIDDATA;
1899  }
1900  }
1901 
1902  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1903  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1904 
1905  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1906 
1907  /* set variable's name */
1908  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1909 
1910 #ifndef NDEBUG
1911  (*var)->scip = set->scip;
1912 #endif
1913  (*var)->obj = obj;
1914  (*var)->unchangedobj = obj;
1915  (*var)->branchfactor = 1.0;
1916  (*var)->rootsol = 0.0;
1917  (*var)->bestrootsol = 0.0;
1918  (*var)->bestrootredcost = 0.0;
1919  (*var)->bestrootlpobjval = SCIP_INVALID;
1920  (*var)->relaxsol = 0.0;
1921  (*var)->nlpsol = 0.0;
1922  (*var)->primsolavg = 0.5 * (lb + ub);
1923  (*var)->conflictlb = SCIP_REAL_MIN;
1924  (*var)->conflictub = SCIP_REAL_MAX;
1925  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1926  (*var)->conflictrelaxedub = (*var)->conflictub;
1927  (*var)->lazylb = -SCIPsetInfinity(set);
1928  (*var)->lazyub = SCIPsetInfinity(set);
1929  (*var)->glbdom.holelist = NULL;
1930  (*var)->glbdom.lb = lb;
1931  (*var)->glbdom.ub = ub;
1932  (*var)->locdom.holelist = NULL;
1933  (*var)->locdom.lb = lb;
1934  (*var)->locdom.ub = ub;
1935  (*var)->varcopy = varcopy;
1936  (*var)->vardelorig = vardelorig;
1937  (*var)->vartrans = vartrans;
1938  (*var)->vardeltrans = vardeltrans;
1939  (*var)->vardata = vardata;
1940  (*var)->parentvars = NULL;
1941  (*var)->negatedvar = NULL;
1942  (*var)->vlbs = NULL;
1943  (*var)->vubs = NULL;
1944  (*var)->implics = NULL;
1945  (*var)->cliquelist = NULL;
1946  (*var)->eventfilter = NULL;
1947  (*var)->lbchginfos = NULL;
1948  (*var)->ubchginfos = NULL;
1949  (*var)->index = stat->nvaridx;
1950  (*var)->probindex = -1;
1951  (*var)->pseudocandindex = -1;
1952  (*var)->eventqueueindexobj = -1;
1953  (*var)->eventqueueindexlb = -1;
1954  (*var)->eventqueueindexub = -1;
1955  (*var)->parentvarssize = 0;
1956  (*var)->nparentvars = 0;
1957  (*var)->nuses = 0;
1958  (*var)->branchpriority = 0;
1959  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1960  (*var)->lbchginfossize = 0;
1961  (*var)->nlbchginfos = 0;
1962  (*var)->ubchginfossize = 0;
1963  (*var)->nubchginfos = 0;
1964  (*var)->conflictlbcount = 0;
1965  (*var)->conflictubcount = 0;
1966  (*var)->closestvlbidx = -1;
1967  (*var)->closestvubidx = -1;
1968  (*var)->closestvblpcount = -1;
1969  (*var)->initial = initial;
1970  (*var)->removable = removable;
1971  (*var)->deleted = FALSE;
1972  (*var)->donotmultaggr = FALSE;
1973  (*var)->vartype = vartype; /*lint !e641*/
1974  (*var)->pseudocostflag = FALSE;
1975  (*var)->eventqueueimpl = FALSE;
1976  (*var)->deletable = FALSE;
1977  (*var)->delglobalstructs = FALSE;
1978 
1979  for( i = 0; i < NLOCKTYPES; i++ )
1980  {
1981  (*var)->nlocksdown[i] = 0;
1982  (*var)->nlocksup[i] = 0;
1983  }
1984 
1985  stat->nvaridx++;
1986 
1987  /* create branching and inference history entries */
1988  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1989  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1990 
1991  /* the value based history is only created on demand */
1992  (*var)->valuehistory = NULL;
1993 
1994  return SCIP_OKAY;
1995 }
1996 
1997 /** creates and captures an original problem variable; an integer variable with bounds
1998  * zero and one is automatically converted into a binary variable
1999  */
2001  SCIP_VAR** var, /**< pointer to variable data */
2002  BMS_BLKMEM* blkmem, /**< block memory */
2003  SCIP_SET* set, /**< global SCIP settings */
2004  SCIP_STAT* stat, /**< problem statistics */
2005  const char* name, /**< name of variable, or NULL for automatic name creation */
2006  SCIP_Real lb, /**< lower bound of variable */
2007  SCIP_Real ub, /**< upper bound of variable */
2008  SCIP_Real obj, /**< objective function value */
2009  SCIP_VARTYPE vartype, /**< type of variable */
2010  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2011  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2012  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2013  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2014  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2015  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2016  SCIP_VARDATA* vardata /**< user data for this specific variable */
2017  )
2018 {
2019  assert(var != NULL);
2020  assert(blkmem != NULL);
2021  assert(stat != NULL);
2022 
2023  /* create variable */
2024  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2025  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2026 
2027  /* set variable status and data */
2028  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2029  (*var)->data.original.origdom.holelist = NULL;
2030  (*var)->data.original.origdom.lb = lb;
2031  (*var)->data.original.origdom.ub = ub;
2032  (*var)->data.original.transvar = NULL;
2033 
2034  /* capture variable */
2035  SCIPvarCapture(*var);
2036 
2037  return SCIP_OKAY;
2038 }
2039 
2040 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2041  * zero and one is automatically converted into a binary variable
2042  */
2044  SCIP_VAR** var, /**< pointer to variable data */
2045  BMS_BLKMEM* blkmem, /**< block memory */
2046  SCIP_SET* set, /**< global SCIP settings */
2047  SCIP_STAT* stat, /**< problem statistics */
2048  const char* name, /**< name of variable, or NULL for automatic name creation */
2049  SCIP_Real lb, /**< lower bound of variable */
2050  SCIP_Real ub, /**< upper bound of variable */
2051  SCIP_Real obj, /**< objective function value */
2052  SCIP_VARTYPE vartype, /**< type of variable */
2053  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2054  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2055  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2056  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2057  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2058  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2059  SCIP_VARDATA* vardata /**< user data for this specific variable */
2060  )
2061 {
2062  assert(var != NULL);
2063  assert(blkmem != NULL);
2064 
2065  /* create variable */
2066  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2067  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2068 
2069  /* create event filter for transformed variable */
2070  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2071 
2072  /* set variable status and data */
2073  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2074 
2075  /* capture variable */
2076  SCIPvarCapture(*var);
2077 
2078  return SCIP_OKAY;
2079 }
2080 
2081 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2082  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2083  * copied at all
2084  */
2086  SCIP_VAR** var, /**< pointer to store the target variable */
2087  BMS_BLKMEM* blkmem, /**< block memory */
2088  SCIP_SET* set, /**< global SCIP settings */
2089  SCIP_STAT* stat, /**< problem statistics */
2090  SCIP* sourcescip, /**< source SCIP data structure */
2091  SCIP_VAR* sourcevar, /**< source variable */
2092  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2093  * target variables */
2094  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2095  * target constraints */
2096  SCIP_Bool global /**< should global or local bounds be used? */
2097  )
2098 {
2099  SCIP_VARDATA* targetdata;
2100  SCIP_RESULT result;
2101  SCIP_Real lb;
2102  SCIP_Real ub;
2103 
2104  assert(set != NULL);
2105  assert(blkmem != NULL);
2106  assert(stat != NULL);
2107  assert(sourcescip != NULL);
2108  assert(sourcevar != NULL);
2109  assert(var != NULL);
2110  assert(set->stage == SCIP_STAGE_PROBLEM);
2111  assert(varmap != NULL);
2112  assert(consmap != NULL);
2113 
2114  /** @todo copy hole lists */
2115  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2116  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2117 
2118  result = SCIP_DIDNOTRUN;
2119  targetdata = NULL;
2120 
2121  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2122  {
2123  lb = SCIPvarGetLbOriginal(sourcevar);
2124  ub = SCIPvarGetUbOriginal(sourcevar);
2125  }
2126  else
2127  {
2128  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2129  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2130  }
2131 
2132  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2133  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2134  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2135  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2136  NULL, NULL, NULL, NULL, NULL) );
2137  assert(*var != NULL);
2138 
2139  /* directly copy donotmultaggr flag */
2140  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2141 
2142  /* insert variable into mapping between source SCIP and the target SCIP */
2143  assert(!SCIPhashmapExists(varmap, sourcevar));
2144  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2145 
2146  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2147  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2148  {
2149  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2150  varmap, consmap, (*var), &targetdata, &result) );
2151 
2152  /* evaluate result */
2153  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2154  {
2155  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2156  return SCIP_INVALIDRESULT;
2157  }
2158 
2159  assert(targetdata == NULL || result == SCIP_SUCCESS);
2160 
2161  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2162  if( result == SCIP_SUCCESS )
2163  {
2164  (*var)->varcopy = sourcevar->varcopy;
2165  (*var)->vardelorig = sourcevar->vardelorig;
2166  (*var)->vartrans = sourcevar->vartrans;
2167  (*var)->vardeltrans = sourcevar->vardeltrans;
2168  (*var)->vardata = targetdata;
2169  }
2170  }
2171 
2172  /* we initialize histories of the variables by copying the source variable-information */
2173  if( set->history_allowtransfer )
2174  {
2175  SCIPvarMergeHistories((*var), sourcevar, stat);
2176  }
2177 
2178  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2179  * methods
2180  */
2181  if( result == SCIP_SUCCESS )
2182  {
2183  (*var)->varcopy = sourcevar->varcopy;
2184  (*var)->vardelorig = sourcevar->vardelorig;
2185  (*var)->vartrans = sourcevar->vartrans;
2186  (*var)->vardeltrans = sourcevar->vardeltrans;
2187  (*var)->vardata = targetdata;
2188  }
2189 
2190  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2191 
2192  return SCIP_OKAY;
2193 }
2194 
2195 /** parse given string for a SCIP_Real bound */
2196 static
2198  SCIP_SET* set, /**< global SCIP settings */
2199  const char* str, /**< string to parse */
2200  SCIP_Real* value, /**< pointer to store the parsed value */
2201  char** endptr /**< pointer to store the final string position if successfully parsed */
2202  )
2203 {
2204  /* first check for infinity value */
2205  if( strncmp(str, "+inf", 4) == 0 )
2206  {
2207  *value = SCIPsetInfinity(set);
2208  (*endptr) = (char*)str + 4;
2209  }
2210  else if( strncmp(str, "-inf", 4) == 0 )
2211  {
2212  *value = -SCIPsetInfinity(set);
2213  (*endptr) = (char*)str + 4;
2214  }
2215  else
2216  {
2217  if( !SCIPstrToRealValue(str, value, endptr) )
2218  {
2219  SCIPerrorMessage("expected value: %s.\n", str);
2220  return SCIP_READERROR;
2221  }
2222  }
2223 
2224  return SCIP_OKAY;
2225 }
2226 
2227 /** parse the characters as bounds */
2228 static
2230  SCIP_SET* set, /**< global SCIP settings */
2231  const char* str, /**< string to parse */
2232  char* type, /**< bound type (global, local, or lazy) */
2233  SCIP_Real* lb, /**< pointer to store the lower bound */
2234  SCIP_Real* ub, /**< pointer to store the upper bound */
2235  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2236  )
2237 {
2238  char token[SCIP_MAXSTRLEN];
2239  char* tmpend;
2240 
2241  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2242 
2243  /* get bound type */
2244  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2245  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2246  {
2247  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2248  *endptr = NULL;
2249  return SCIP_OKAY;
2250  }
2251 
2252  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2253 
2254  /* get lower bound */
2255  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2256  str = *endptr;
2257  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2258 
2259  /* get upper bound */
2260  SCIP_CALL( parseValue(set, str, ub, endptr) );
2261 
2262  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2263 
2264  /* skip end of bounds */
2265  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2266  ++(*endptr);
2267 
2268  return SCIP_OKAY;
2269 }
2270 
2271 /** parses a given string for a variable informations */
2272 static
2274  SCIP_SET* set, /**< global SCIP settings */
2275  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2276  const char* str, /**< string to parse */
2277  char* name, /**< pointer to store the variable name */
2278  SCIP_Real* lb, /**< pointer to store the lower bound */
2279  SCIP_Real* ub, /**< pointer to store the upper bound */
2280  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2281  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2282  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2283  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2284  SCIP_Bool local, /**< should the local bound be applied */
2285  char** endptr, /**< pointer to store the final string position if successfully */
2286  SCIP_Bool* success /**< pointer store if the paring process was successful */
2287  )
2288 {
2289  SCIP_Real parsedlb;
2290  SCIP_Real parsedub;
2291  char token[SCIP_MAXSTRLEN];
2292  char* strptr;
2293  int i;
2294 
2295  assert(lb != NULL);
2296  assert(ub != NULL);
2297  assert(obj != NULL);
2298  assert(vartype != NULL);
2299  assert(lazylb != NULL);
2300  assert(lazyub != NULL);
2301  assert(success != NULL);
2302 
2303  (*success) = TRUE;
2304 
2305  /* copy variable type */
2306  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2307  assert(str != *endptr);
2308  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2309 
2310  /* get variable type */
2311  if( strncmp(token, "binary", 3) == 0 )
2312  (*vartype) = SCIP_VARTYPE_BINARY;
2313  else if( strncmp(token, "integer", 3) == 0 )
2314  (*vartype) = SCIP_VARTYPE_INTEGER;
2315  else if( strncmp(token, "implicit", 3) == 0 )
2316  (*vartype) = SCIP_VARTYPE_IMPLINT;
2317  else if( strncmp(token, "continuous", 3) == 0 )
2318  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2319  else
2320  {
2321  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2322  (*success) = FALSE;
2323  return SCIP_OKAY;
2324  }
2325 
2326  /* move string pointer behind variable type */
2327  str = *endptr;
2328 
2329  /* get variable name */
2330  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2331  assert(endptr != NULL);
2332  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2333 
2334  /* move string pointer behind variable name */
2335  str = *endptr;
2336 
2337  /* cut out objective coefficient */
2338  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2339 
2340  /* move string pointer behind objective coefficient */
2341  str = *endptr;
2342 
2343  /* get objective coefficient */
2344  if( !SCIPstrToRealValue(token, obj, endptr) )
2345  {
2346  *endptr = NULL;
2347  return SCIP_READERROR;
2348  }
2349 
2350  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2351 
2352  /* parse global/original bounds */
2353  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2354  if ( *endptr == NULL )
2355  {
2356  SCIPerrorMessage("Expected bound type: %s.\n", token);
2357  return SCIP_READERROR;
2358  }
2359  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2360 
2361  /* initialize the lazy bound */
2362  *lazylb = -SCIPsetInfinity(set);
2363  *lazyub = SCIPsetInfinity(set);
2364 
2365  /* store pointer */
2366  strptr = *endptr;
2367 
2368  /* possibly parse optional local and lazy bounds */
2369  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2370  {
2371  /* start after previous bounds */
2372  strptr = *endptr;
2373 
2374  /* parse global bounds */
2375  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2376 
2377  /* stop if parsing of bounds failed */
2378  if( *endptr == NULL )
2379  break;
2380 
2381  if( strncmp(token, "local", 5) == 0 && local )
2382  {
2383  *lb = parsedlb;
2384  *ub = parsedub;
2385  }
2386  else if( strncmp(token, "lazy", 4) == 0 )
2387  {
2388  *lazylb = parsedlb;
2389  *lazyub = parsedub;
2390  }
2391  }
2392 
2393  /* restore pointer */
2394  if ( *endptr == NULL )
2395  *endptr = strptr;
2396 
2397  /* check bounds for binary variables */
2398  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2399  {
2400  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2401  {
2402  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2403  return SCIP_READERROR;
2404  }
2405  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2406  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2407  {
2408  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2409  return SCIP_READERROR;
2410  }
2411  }
2412 
2413  return SCIP_OKAY;
2414 }
2415 
2416 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2417  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2418  * integer variable with bounds zero and one is automatically converted into a binary variable
2419  */
2421  SCIP_VAR** var, /**< pointer to variable data */
2422  BMS_BLKMEM* blkmem, /**< block memory */
2423  SCIP_SET* set, /**< global SCIP settings */
2424  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2425  SCIP_STAT* stat, /**< problem statistics */
2426  const char* str, /**< string to parse */
2427  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2428  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2429  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2430  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2431  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2432  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2433  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2434  char** endptr, /**< pointer to store the final string position if successfully */
2435  SCIP_Bool* success /**< pointer store if the paring process was successful */
2436  )
2437 {
2438  char name[SCIP_MAXSTRLEN];
2439  SCIP_Real lb;
2440  SCIP_Real ub;
2441  SCIP_Real obj;
2442  SCIP_VARTYPE vartype;
2443  SCIP_Real lazylb;
2444  SCIP_Real lazyub;
2445 
2446  assert(var != NULL);
2447  assert(blkmem != NULL);
2448  assert(stat != NULL);
2449  assert(endptr != NULL);
2450  assert(success != NULL);
2451 
2452  /* parse string in cip format for variable information */
2453  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2454 
2455  if( *success )
2456  {
2457  /* create variable */
2458  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2459  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2460 
2461  /* set variable status and data */
2462  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2463  (*var)->data.original.origdom.holelist = NULL;
2464  (*var)->data.original.origdom.lb = lb;
2465  (*var)->data.original.origdom.ub = ub;
2466  (*var)->data.original.transvar = NULL;
2467 
2468  /* set lazy status of variable bounds */
2469  (*var)->lazylb = lazylb;
2470  (*var)->lazyub = lazyub;
2471 
2472  /* capture variable */
2473  SCIPvarCapture(*var);
2474  }
2475 
2476  return SCIP_OKAY;
2477 }
2478 
2479 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2480  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2481  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2482  * variable
2483  */
2485  SCIP_VAR** var, /**< pointer to variable data */
2486  BMS_BLKMEM* blkmem, /**< block memory */
2487  SCIP_SET* set, /**< global SCIP settings */
2488  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2489  SCIP_STAT* stat, /**< problem statistics */
2490  const char* str, /**< string to parse */
2491  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2492  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2493  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2494  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2495  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2496  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2497  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2498  char** endptr, /**< pointer to store the final string position if successfully */
2499  SCIP_Bool* success /**< pointer store if the paring process was successful */
2500  )
2501 {
2502  char name[SCIP_MAXSTRLEN];
2503  SCIP_Real lb;
2504  SCIP_Real ub;
2505  SCIP_Real obj;
2506  SCIP_VARTYPE vartype;
2507  SCIP_Real lazylb;
2508  SCIP_Real lazyub;
2509 
2510  assert(var != NULL);
2511  assert(blkmem != NULL);
2512  assert(endptr != NULL);
2513  assert(success != NULL);
2514 
2515  /* parse string in cip format for variable information */
2516  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2517 
2518  if( *success )
2519  {
2520  /* create variable */
2521  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2522  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2523 
2524  /* create event filter for transformed variable */
2525  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2526 
2527  /* set variable status and data */
2528  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2529 
2530  /* set lazy status of variable bounds */
2531  (*var)->lazylb = lazylb;
2532  (*var)->lazyub = lazyub;
2533 
2534  /* capture variable */
2535  SCIPvarCapture(*var);
2536  }
2537 
2538  return SCIP_OKAY;
2539 }
2540 
2541 /** ensures, that parentvars array of var can store at least num entries */
2542 static
2544  SCIP_VAR* var, /**< problem variable */
2545  BMS_BLKMEM* blkmem, /**< block memory */
2546  SCIP_SET* set, /**< global SCIP settings */
2547  int num /**< minimum number of entries to store */
2548  )
2549 {
2550  assert(var->nparentvars <= var->parentvarssize);
2551 
2552  if( num > var->parentvarssize )
2553  {
2554  int newsize;
2555 
2556  newsize = SCIPsetCalcMemGrowSize(set, num);
2557  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2558  var->parentvarssize = newsize;
2559  }
2560  assert(num <= var->parentvarssize);
2561 
2562  return SCIP_OKAY;
2563 }
2564 
2565 /** adds variable to parent list of a variable and captures parent variable */
2566 static
2568  SCIP_VAR* var, /**< variable to add parent to */
2569  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2570  SCIP_SET* set, /**< global SCIP settings */
2571  SCIP_VAR* parentvar /**< parent variable to add */
2572  )
2573 {
2574  assert(var != NULL);
2575  assert(parentvar != NULL);
2576 
2577  /* the direct original counterpart must be stored as first parent */
2578  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2579 
2580  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2581  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2582 
2583  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2584 
2585  var->parentvars[var->nparentvars] = parentvar;
2586  var->nparentvars++;
2587 
2588  SCIPvarCapture(parentvar);
2589 
2590  return SCIP_OKAY;
2591 }
2592 
2593 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2594 static
2596  SCIP_VAR** var, /**< pointer to variable */
2597  BMS_BLKMEM* blkmem, /**< block memory */
2598  SCIP_SET* set, /**< global SCIP settings */
2599  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2600  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2601  )
2602 {
2603  SCIP_VAR* parentvar;
2604  int i;
2605 
2606  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2607 
2608  /* release the parent variables and remove the link from the parent variable to the child */
2609  for( i = 0; i < (*var)->nparentvars; ++i )
2610  {
2611  assert((*var)->parentvars != NULL);
2612  parentvar = (*var)->parentvars[i];
2613  assert(parentvar != NULL);
2614 
2615  switch( SCIPvarGetStatus(parentvar) )
2616  {
2618  assert(parentvar->data.original.transvar == *var);
2619  assert(&parentvar->data.original.transvar != var);
2620  parentvar->data.original.transvar = NULL;
2621  break;
2622 
2624  assert(parentvar->data.aggregate.var == *var);
2625  assert(&parentvar->data.aggregate.var != var);
2626  parentvar->data.aggregate.var = NULL;
2627  break;
2628 
2629 #if 0
2630  /* The following code is unclear: should the current variable be removed from its parents? */
2632  assert(parentvar->data.multaggr.vars != NULL);
2633  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2634  {}
2635  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2636  if( v < parentvar->data.multaggr.nvars-1 )
2637  {
2638  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2639  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2640  }
2641  parentvar->data.multaggr.nvars--;
2642  break;
2643 #endif
2644 
2646  assert(parentvar->negatedvar == *var);
2647  assert((*var)->negatedvar == parentvar);
2648  parentvar->negatedvar = NULL;
2649  (*var)->negatedvar = NULL;
2650  break;
2651 
2652  default:
2653  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2654  return SCIP_INVALIDDATA;
2655  } /*lint !e788*/
2656 
2657  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2658  }
2659 
2660  /* free parentvars array */
2661  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2662 
2663  return SCIP_OKAY;
2664 }
2665 
2666 /** frees a variable */
2667 static
2669  SCIP_VAR** var, /**< pointer to variable */
2670  BMS_BLKMEM* blkmem, /**< block memory */
2671  SCIP_SET* set, /**< global SCIP settings */
2672  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2673  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2674  )
2675 {
2676  assert(var != NULL);
2677  assert(*var != NULL);
2678  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2679  assert((*var)->nuses == 0);
2680  assert((*var)->probindex == -1);
2681 
2682  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2683 
2684  switch( SCIPvarGetStatus(*var) )
2685  {
2687  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2688  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2689  assert((*var)->data.original.origdom.holelist == NULL);
2690  break;
2691  case SCIP_VARSTATUS_LOOSE:
2692  break;
2693  case SCIP_VARSTATUS_COLUMN:
2694  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2695  break;
2696  case SCIP_VARSTATUS_FIXED:
2698  break;
2700  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2701  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2702  break;
2704  break;
2705  default:
2706  SCIPerrorMessage("unknown variable status\n");
2707  return SCIP_INVALIDDATA;
2708  }
2709 
2710  /* release all parent variables and free the parentvars array */
2711  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2712 
2713  /* free user data */
2715  {
2716  if( (*var)->vardelorig != NULL )
2717  {
2718  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2719  }
2720  }
2721  else
2722  {
2723  if( (*var)->vardeltrans != NULL )
2724  {
2725  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2726  }
2727  }
2728 
2729  /* free event filter */
2730  if( (*var)->eventfilter != NULL )
2731  {
2732  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2733  }
2734  assert((*var)->eventfilter == NULL);
2735 
2736  /* free hole lists */
2737  holelistFree(&(*var)->glbdom.holelist, blkmem);
2738  holelistFree(&(*var)->locdom.holelist, blkmem);
2739  assert((*var)->glbdom.holelist == NULL);
2740  assert((*var)->locdom.holelist == NULL);
2741 
2742  /* free variable bounds data structures */
2743  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2744  SCIPvboundsFree(&(*var)->vubs, blkmem);
2745 
2746  /* free implications data structures */
2747  SCIPimplicsFree(&(*var)->implics, blkmem);
2748 
2749  /* free clique list data structures */
2750  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2751 
2752  /* free bound change information arrays */
2753  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2754  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2755 
2756  /* free branching and inference history entries */
2757  SCIPhistoryFree(&(*var)->history, blkmem);
2758  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2759  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2760 
2761  /* free variable data structure */
2762  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2763  BMSfreeBlockMemory(blkmem, var);
2764 
2765  return SCIP_OKAY;
2766 }
2767 
2768 /** increases usage counter of variable */
2769 void SCIPvarCapture(
2770  SCIP_VAR* var /**< variable */
2771  )
2772 {
2773  assert(var != NULL);
2774  assert(var->nuses >= 0);
2775 
2776  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2777  var->nuses++;
2778 }
2779 
2780 /** decreases usage counter of variable, and frees memory if necessary */
2782  SCIP_VAR** var, /**< pointer to variable */
2783  BMS_BLKMEM* blkmem, /**< block memory */
2784  SCIP_SET* set, /**< global SCIP settings */
2785  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2786  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2787  )
2788 {
2789  assert(var != NULL);
2790  assert(*var != NULL);
2791  assert((*var)->nuses >= 1);
2792  assert(blkmem != NULL);
2793  assert((*var)->scip == set->scip);
2794 
2795  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2796  (*var)->nuses--;
2797  if( (*var)->nuses == 0 )
2798  {
2799  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2800  }
2801 
2802  *var = NULL;
2803 
2804  return SCIP_OKAY;
2805 }
2806 
2807 /** change variable name */
2809  SCIP_VAR* var, /**< problem variable */
2810  BMS_BLKMEM* blkmem, /**< block memory */
2811  const char* name /**< name of variable */
2812  )
2813 {
2814  assert(name != NULL);
2815 
2816  /* remove old variable name */
2817  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2818 
2819  /* set new variable name */
2820  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2821 
2822  return SCIP_OKAY;
2823 }
2824 
2825 /** initializes variable data structure for solving */
2826 void SCIPvarInitSolve(
2827  SCIP_VAR* var /**< problem variable */
2828  )
2829 {
2830  assert(var != NULL);
2831 
2833  var->conflictlbcount = 0;
2834  var->conflictubcount = 0;
2835 }
2836 
2837 /** outputs the given bounds into the file stream */
2838 static
2839 void printBounds(
2840  SCIP_SET* set, /**< global SCIP settings */
2841  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2842  FILE* file, /**< output file (or NULL for standard output) */
2843  SCIP_Real lb, /**< lower bound */
2844  SCIP_Real ub, /**< upper bound */
2845  const char* name /**< bound type name */
2846  )
2847 {
2848  assert(set != NULL);
2849 
2850  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2851  if( SCIPsetIsInfinity(set, lb) )
2852  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2853  else if( SCIPsetIsInfinity(set, -lb) )
2854  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2855  else
2856  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2857  if( SCIPsetIsInfinity(set, ub) )
2858  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2859  else if( SCIPsetIsInfinity(set, -ub) )
2860  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2861  else
2862  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2863 }
2864 
2865 /** prints hole list to file stream */
2866 static
2867 void printHolelist(
2868  SCIP_SET* set, /**< global SCIP settings */
2869  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2870  FILE* file, /**< output file (or NULL for standard output) */
2871  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2872  const char* name /**< hole type name */
2873  )
2874 { /*lint --e{715}*/
2875  SCIP_Real left;
2876  SCIP_Real right;
2877 
2878  if( holelist == NULL )
2879  return;
2880 
2881  left = SCIPholelistGetLeft(holelist);
2882  right = SCIPholelistGetRight(holelist);
2883 
2884  /* display first hole */
2885  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2886  holelist = SCIPholelistGetNext(holelist);
2887 
2888  while(holelist != NULL )
2889  {
2890  left = SCIPholelistGetLeft(holelist);
2891  right = SCIPholelistGetRight(holelist);
2892 
2893  /* display hole */
2894  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2895 
2896  /* get next hole */
2897  holelist = SCIPholelistGetNext(holelist);
2898  }
2899 }
2900 
2901 /** outputs variable information into file stream */
2903  SCIP_VAR* var, /**< problem variable */
2904  SCIP_SET* set, /**< global SCIP settings */
2905  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2906  FILE* file /**< output file (or NULL for standard output) */
2907  )
2908 {
2909  SCIP_HOLELIST* holelist;
2910  SCIP_Real lb;
2911  SCIP_Real ub;
2912  int i;
2913 
2914  assert(var != NULL);
2915  assert(var->scip == set->scip);
2916 
2917  /* type of variable */
2918  switch( SCIPvarGetType(var) )
2919  {
2920  case SCIP_VARTYPE_BINARY:
2921  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2922  break;
2923  case SCIP_VARTYPE_INTEGER:
2924  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2925  break;
2926  case SCIP_VARTYPE_IMPLINT:
2927  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2928  break;
2930  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2931  break;
2932  default:
2933  SCIPerrorMessage("unknown variable type\n");
2934  SCIPABORT();
2935  return SCIP_ERROR; /*lint !e527*/
2936  }
2937 
2938  /* name */
2939  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2940 
2941  /* objective value */
2942  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2943 
2944  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2945  if( !SCIPvarIsTransformed(var) )
2946  {
2947  /* output original bound */
2948  lb = SCIPvarGetLbOriginal(var);
2949  ub = SCIPvarGetUbOriginal(var);
2950  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2951 
2952  /* output lazy bound */
2953  lb = SCIPvarGetLbLazy(var);
2954  ub = SCIPvarGetUbLazy(var);
2955 
2956  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2957  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2958  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2959 
2960  holelist = SCIPvarGetHolelistOriginal(var);
2961  printHolelist(set, messagehdlr, file, holelist, "original holes");
2962  }
2963  else
2964  {
2965  /* output global bound */
2966  lb = SCIPvarGetLbGlobal(var);
2967  ub = SCIPvarGetUbGlobal(var);
2968  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2969 
2970  /* output local bound */
2971  lb = SCIPvarGetLbLocal(var);
2972  ub = SCIPvarGetUbLocal(var);
2973  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2974 
2975  /* output lazy bound */
2976  lb = SCIPvarGetLbLazy(var);
2977  ub = SCIPvarGetUbLazy(var);
2978 
2979  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2980  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2981  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2982 
2983  /* global hole list */
2984  holelist = SCIPvarGetHolelistGlobal(var);
2985  printHolelist(set, messagehdlr, file, holelist, "global holes");
2986 
2987  /* local hole list */
2988  holelist = SCIPvarGetHolelistLocal(var);
2989  printHolelist(set, messagehdlr, file, holelist, "local holes");
2990  }
2991 
2992  /* fixings and aggregations */
2993  switch( SCIPvarGetStatus(var) )
2994  {
2996  case SCIP_VARSTATUS_LOOSE:
2997  case SCIP_VARSTATUS_COLUMN:
2998  break;
2999 
3000  case SCIP_VARSTATUS_FIXED:
3001  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3002  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3003  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3004  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3005  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3006  else
3007  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3008  break;
3009 
3011  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3012  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3013  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3014  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3015  break;
3016 
3018  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3019  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3020  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3021  for( i = 0; i < var->data.multaggr.nvars; ++i )
3022  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3023  break;
3024 
3026  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3027  break;
3028 
3029  default:
3030  SCIPerrorMessage("unknown variable status\n");
3031  SCIPABORT();
3032  return SCIP_ERROR; /*lint !e527*/
3033  }
3034 
3035  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3036 
3037  return SCIP_OKAY;
3038 }
3039 
3040 /** issues a VARUNLOCKED event on the given variable */
3041 static
3043  SCIP_VAR* var, /**< problem variable to change */
3044  BMS_BLKMEM* blkmem, /**< block memory */
3045  SCIP_SET* set, /**< global SCIP settings */
3046  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3047  )
3048 {
3049  SCIP_EVENT* event;
3050 
3051  assert(var != NULL);
3052  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3053  assert(var->scip == set->scip);
3054 
3055  /* issue VARUNLOCKED event on variable */
3056  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3057  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3058 
3059  return SCIP_OKAY;
3060 }
3061 
3062 /** modifies lock numbers for rounding */
3064  SCIP_VAR* var, /**< problem variable */
3065  BMS_BLKMEM* blkmem, /**< block memory */
3066  SCIP_SET* set, /**< global SCIP settings */
3067  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3068  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3069  int addnlocksdown, /**< increase in number of rounding down locks */
3070  int addnlocksup /**< increase in number of rounding up locks */
3071  )
3072 {
3073  SCIP_VAR* lockvar;
3074 
3075  assert(var != NULL);
3076  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3077  assert(var->nlocksup[locktype] >= 0);
3078  assert(var->nlocksdown[locktype] >= 0);
3079  assert(var->scip == set->scip);
3080 
3081  if( addnlocksdown == 0 && addnlocksup == 0 )
3082  return SCIP_OKAY;
3083 
3084 #ifdef SCIP_DEBUG
3085  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3086  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3087 #endif
3088 
3089  lockvar = var;
3090 
3091  while( TRUE ) /*lint !e716 */
3092  {
3093  assert(lockvar != NULL);
3094 
3095  switch( SCIPvarGetStatus(lockvar) )
3096  {
3098  if( lockvar->data.original.transvar != NULL )
3099  {
3100  lockvar = lockvar->data.original.transvar;
3101  break;
3102  }
3103  else
3104  {
3105  lockvar->nlocksdown[locktype] += addnlocksdown;
3106  lockvar->nlocksup[locktype] += addnlocksup;
3107 
3108  assert(lockvar->nlocksdown[locktype] >= 0);
3109  assert(lockvar->nlocksup[locktype] >= 0);
3110 
3111  return SCIP_OKAY;
3112  }
3113  case SCIP_VARSTATUS_LOOSE:
3114  case SCIP_VARSTATUS_COLUMN:
3115  case SCIP_VARSTATUS_FIXED:
3116  lockvar->nlocksdown[locktype] += addnlocksdown;
3117  lockvar->nlocksup[locktype] += addnlocksup;
3118 
3119  assert(lockvar->nlocksdown[locktype] >= 0);
3120  assert(lockvar->nlocksup[locktype] >= 0);
3121 
3122  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3123  && lockvar->nlocksup[locktype] <= 1 )
3124  {
3125  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3126  }
3127 
3128  return SCIP_OKAY;
3130  if( lockvar->data.aggregate.scalar < 0.0 )
3131  {
3132  int tmp = addnlocksup;
3133 
3134  addnlocksup = addnlocksdown;
3135  addnlocksdown = tmp;
3136  }
3137 
3138  lockvar = lockvar->data.aggregate.var;
3139  break;
3141  {
3142  int v;
3143 
3144  assert(!lockvar->donotmultaggr);
3145 
3146  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3147  {
3148  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3149  {
3150  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3151  addnlocksup) );
3152  }
3153  else
3154  {
3155  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3156  addnlocksdown) );
3157  }
3158  }
3159  return SCIP_OKAY;
3160  }
3162  {
3163  int tmp = addnlocksup;
3164 
3165  assert(lockvar->negatedvar != NULL);
3166  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3167  assert(lockvar->negatedvar->negatedvar == lockvar);
3168 
3169  addnlocksup = addnlocksdown;
3170  addnlocksdown = tmp;
3171 
3172  lockvar = lockvar->negatedvar;
3173  break;
3174  }
3175  default:
3176  SCIPerrorMessage("unknown variable status\n");
3177  return SCIP_INVALIDDATA;
3178  }
3179  }
3180 }
3181 
3182 /** gets number of locks for rounding down of a special type */
3184  SCIP_VAR* var, /**< problem variable */
3185  SCIP_LOCKTYPE locktype /**< type of variable locks */
3186  )
3187 {
3188  int nlocks;
3189  int i;
3190 
3191  assert(var != NULL);
3192  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3193  assert(var->nlocksdown[locktype] >= 0);
3194 
3195  switch( SCIPvarGetStatus(var) )
3196  {
3198  if( var->data.original.transvar != NULL )
3199  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3200  else
3201  return var->nlocksdown[locktype];
3202 
3203  case SCIP_VARSTATUS_LOOSE:
3204  case SCIP_VARSTATUS_COLUMN:
3205  case SCIP_VARSTATUS_FIXED:
3206  return var->nlocksdown[locktype];
3207 
3209  if( var->data.aggregate.scalar > 0.0 )
3210  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3211  else
3212  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3213 
3215  assert(!var->donotmultaggr);
3216  nlocks = 0;
3217  for( i = 0; i < var->data.multaggr.nvars; ++i )
3218  {
3219  if( var->data.multaggr.scalars[i] > 0.0 )
3220  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3221  else
3222  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3223  }
3224  return nlocks;
3225 
3227  assert(var->negatedvar != NULL);
3229  assert(var->negatedvar->negatedvar == var);
3230  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3231 
3232  default:
3233  SCIPerrorMessage("unknown variable status\n");
3234  SCIPABORT();
3235  return INT_MAX; /*lint !e527*/
3236  }
3237 }
3238 
3239 /** gets number of locks for rounding up of a special type */
3241  SCIP_VAR* var, /**< problem variable */
3242  SCIP_LOCKTYPE locktype /**< type of variable locks */
3243  )
3244 {
3245  int nlocks;
3246  int i;
3247 
3248  assert(var != NULL);
3249  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568q*/
3250  assert(var->nlocksup[locktype] >= 0);
3251 
3252  switch( SCIPvarGetStatus(var) )
3253  {
3255  if( var->data.original.transvar != NULL )
3256  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3257  else
3258  return var->nlocksup[locktype];
3259 
3260  case SCIP_VARSTATUS_LOOSE:
3261  case SCIP_VARSTATUS_COLUMN:
3262  case SCIP_VARSTATUS_FIXED:
3263  return var->nlocksup[locktype];
3264 
3266  if( var->data.aggregate.scalar > 0.0 )
3267  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3268  else
3269  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3270 
3272  assert(!var->donotmultaggr);
3273  nlocks = 0;
3274  for( i = 0; i < var->data.multaggr.nvars; ++i )
3275  {
3276  if( var->data.multaggr.scalars[i] > 0.0 )
3277  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3278  else
3279  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3280  }
3281  return nlocks;
3282 
3284  assert(var->negatedvar != NULL);
3286  assert(var->negatedvar->negatedvar == var);
3287  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3288 
3289  default:
3290  SCIPerrorMessage("unknown variable status\n");
3291  SCIPABORT();
3292  return INT_MAX; /*lint !e527*/
3293  }
3294 }
3295 
3296 /** gets number of locks for rounding down
3297  *
3298  * @note This method will always return variable locks of type model
3299  *
3300  * @note It is recommented to use SCIPvarGetNLocksDownType()
3301  */
3303  SCIP_VAR* var /**< problem variable */
3304  )
3305 {
3307 }
3308 
3309 /** gets number of locks for rounding up
3310  *
3311  * @note This method will always return variable locks of type model
3312  *
3313  * @note It is recommented to use SCIPvarGetNLocksUpType()
3314  */
3315 int SCIPvarGetNLocksUp(
3316  SCIP_VAR* var /**< problem variable */
3317  )
3318 {
3320 }
3321 
3322 /** is it possible, to round variable down and stay feasible?
3323  *
3324  * @note This method will always check w.r.t variable locks of type model
3325  */
3327  SCIP_VAR* var /**< problem variable */
3328  )
3329 {
3330  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3331 }
3332 
3333 /** is it possible, to round variable up and stay feasible?
3334  *
3335  * @note This method will always check w.r.t. variable locks of type model
3336  */
3338  SCIP_VAR* var /**< problem variable */
3339  )
3340 {
3341  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3342 }
3343 
3344 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3345  * a new transformed variable for this variable is created
3346  */
3348  SCIP_VAR* origvar, /**< original problem variable */
3349  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3350  SCIP_SET* set, /**< global SCIP settings */
3351  SCIP_STAT* stat, /**< problem statistics */
3352  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3353  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3354  )
3355 {
3356  char name[SCIP_MAXSTRLEN];
3357 
3358  assert(origvar != NULL);
3359  assert(origvar->scip == set->scip);
3360  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3361  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3362  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3363  assert(origvar->vlbs == NULL);
3364  assert(origvar->vubs == NULL);
3365  assert(transvar != NULL);
3366 
3367  /* check if variable is already transformed */
3368  if( origvar->data.original.transvar != NULL )
3369  {
3370  *transvar = origvar->data.original.transvar;
3371  SCIPvarCapture(*transvar);
3372  }
3373  else
3374  {
3375  int i;
3376 
3377  /* create transformed variable */
3378  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3379  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3380  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3381  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3382  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3383 
3384  /* copy the branch factor and priority */
3385  (*transvar)->branchfactor = origvar->branchfactor;
3386  (*transvar)->branchpriority = origvar->branchpriority;
3387  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3388 
3389  /* duplicate hole lists */
3390  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3391  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3392 
3393  /* link original and transformed variable */
3394  origvar->data.original.transvar = *transvar;
3395  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3396 
3397  /* copy rounding locks */
3398  for( i = 0; i < NLOCKTYPES; i++ )
3399  {
3400  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3401  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3402  assert((*transvar)->nlocksdown[i] >= 0);
3403  assert((*transvar)->nlocksup[i] >= 0);
3404  }
3405 
3406  /* copy doNotMultiaggr status */
3407  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3408 
3409  /* copy lazy bounds */
3410  (*transvar)->lazylb = origvar->lazylb;
3411  (*transvar)->lazyub = origvar->lazyub;
3412 
3413  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3414  * when original variable was created
3415  */
3416  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3417 
3418  /* transform user data */
3419  if( origvar->vartrans != NULL )
3420  {
3421  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3422  }
3423  else
3424  (*transvar)->vardata = origvar->vardata;
3425  }
3426 
3427  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3428 
3429  return SCIP_OKAY;
3430 }
3431 
3432 /** gets corresponding transformed variable of an original or negated original variable */
3434  SCIP_VAR* origvar, /**< original problem variable */
3435  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3436  SCIP_SET* set, /**< global SCIP settings */
3437  SCIP_STAT* stat, /**< problem statistics */
3438  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3439  )
3440 {
3441  assert(origvar != NULL);
3443  assert(origvar->scip == set->scip);
3444 
3445  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3446  {
3447  assert(origvar->negatedvar != NULL);
3449 
3450  if( origvar->negatedvar->data.original.transvar == NULL )
3451  *transvar = NULL;
3452  else
3453  {
3454  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3455  }
3456  }
3457  else
3458  *transvar = origvar->data.original.transvar;
3459 
3460  return SCIP_OKAY;
3461 }
3462 
3463 /** converts loose transformed variable into column variable, creates LP column */
3465  SCIP_VAR* var, /**< problem variable */
3466  BMS_BLKMEM* blkmem, /**< block memory */
3467  SCIP_SET* set, /**< global SCIP settings */
3468  SCIP_STAT* stat, /**< problem statistics */
3469  SCIP_PROB* prob, /**< problem data */
3470  SCIP_LP* lp /**< current LP data */
3471  )
3472 {
3473  assert(var != NULL);
3474  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3475  assert(var->scip == set->scip);
3476 
3477  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3478 
3479  /* switch variable status */
3480  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3481 
3482  /* create column of variable */
3483  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3484 
3485  if( var->probindex != -1 )
3486  {
3487  /* inform problem about the variable's status change */
3488  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3489 
3490  /* inform LP, that problem variable is now a column variable and no longer loose */
3491  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3492  }
3493 
3494  return SCIP_OKAY;
3495 }
3496 
3497 /** converts column transformed variable back into loose variable, frees LP column */
3499  SCIP_VAR* var, /**< problem variable */
3500  BMS_BLKMEM* blkmem, /**< block memory */
3501  SCIP_SET* set, /**< global SCIP settings */
3502  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3503  SCIP_PROB* prob, /**< problem data */
3504  SCIP_LP* lp /**< current LP data */
3505  )
3506 {
3507  assert(var != NULL);
3508  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3509  assert(var->scip == set->scip);
3510  assert(var->data.col != NULL);
3511  assert(var->data.col->lppos == -1);
3512  assert(var->data.col->lpipos == -1);
3513 
3514  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3515 
3516  /* free column of variable */
3517  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3518 
3519  /* switch variable status */
3520  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3521 
3522  if( var->probindex != -1 )
3523  {
3524  /* inform problem about the variable's status change */
3525  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3526 
3527  /* inform LP, that problem variable is now a loose variable and no longer a column */
3528  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3529  }
3530 
3531  return SCIP_OKAY;
3532 }
3533 
3534 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3535  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3536  * are not informed about a fixing of an active variable they are pointing to
3537  */
3538 static
3540  SCIP_VAR* var, /**< problem variable to change */
3541  BMS_BLKMEM* blkmem, /**< block memory */
3542  SCIP_SET* set, /**< global SCIP settings */
3543  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3544  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3545  * multi-aggregation(2)
3546  */
3547  )
3548 {
3549  SCIP_EVENT* event;
3550  SCIP_VARSTATUS varstatus;
3551  int i;
3552 
3553  assert(var != NULL);
3554  assert(var->scip == set->scip);
3555  assert(0 <= fixeventtype && fixeventtype <= 2);
3556 
3557  /* issue VARFIXED event on variable */
3558  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3559  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3560 
3561 #ifndef NDEBUG
3562  for( i = var->nparentvars -1; i >= 0; --i )
3563  {
3565  }
3566 #endif
3567 
3568  switch( fixeventtype )
3569  {
3570  case 0:
3571  /* process all parents of a fixed variable */
3572  for( i = var->nparentvars - 1; i >= 0; --i )
3573  {
3574  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3575 
3576  assert(varstatus != SCIP_VARSTATUS_FIXED);
3577 
3578  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3579  * one
3580  */
3581  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3582  {
3583  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3584  }
3585  }
3586  break;
3587  case 1:
3588  /* process all parents of a aggregated variable */
3589  for( i = var->nparentvars - 1; i >= 0; --i )
3590  {
3591  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3592 
3593  assert(varstatus != SCIP_VARSTATUS_FIXED);
3594 
3595  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3596  * issued(, except the original one)
3597  *
3598  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3599  * yet issued
3600  */
3601  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3602  continue;
3603 
3604  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3605  {
3606  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3607  }
3608  }
3609  break;
3610  case 2:
3611  /* process all parents of a aggregated variable */
3612  for( i = var->nparentvars - 1; i >= 0; --i )
3613  {
3614  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3615 
3616  assert(varstatus != SCIP_VARSTATUS_FIXED);
3617 
3618  /* issue event on all parent variables except the original one */
3619  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3620  {
3621  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3622  }
3623  }
3624  break;
3625  default:
3626  SCIPerrorMessage("unknown variable fixation event origin\n");
3627  return SCIP_INVALIDDATA;
3628  }
3629 
3630  return SCIP_OKAY;
3631 }
3632 
3633 /** converts variable into fixed variable */
3635  SCIP_VAR* var, /**< problem variable */
3636  BMS_BLKMEM* blkmem, /**< block memory */
3637  SCIP_SET* set, /**< global SCIP settings */
3638  SCIP_STAT* stat, /**< problem statistics */
3639  SCIP_PROB* transprob, /**< tranformed problem data */
3640  SCIP_PROB* origprob, /**< original problem data */
3641  SCIP_PRIMAL* primal, /**< primal data */
3642  SCIP_TREE* tree, /**< branch and bound tree */
3643  SCIP_REOPT* reopt, /**< reoptimization data structure */
3644  SCIP_LP* lp, /**< current LP data */
3645  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3646  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3647  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3648  SCIP_Real fixedval, /**< value to fix variable at */
3649  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3650  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3651  )
3652 {
3653  SCIP_Real obj;
3654  SCIP_Real childfixedval;
3655 
3656  assert(var != NULL);
3657  assert(var->scip == set->scip);
3658  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3659  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3660  assert(infeasible != NULL);
3661  assert(fixed != NULL);
3662 
3663  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3664 
3665  *infeasible = FALSE;
3666  *fixed = FALSE;
3667 
3669  {
3670  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3671  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3672  return SCIP_OKAY;
3673  }
3674  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3675  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3676  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3677  {
3678  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3679  *infeasible = TRUE;
3680  return SCIP_OKAY;
3681  }
3682 
3683  switch( SCIPvarGetStatus(var) )
3684  {
3686  if( var->data.original.transvar == NULL )
3687  {
3688  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3689  return SCIP_INVALIDDATA;
3690  }
3691  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3692  lp, branchcand, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3693  break;
3694 
3695  case SCIP_VARSTATUS_LOOSE:
3696  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3697 
3698  /* set the fixed variable's objective value to 0.0 */
3699  obj = var->obj;
3700  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3701 
3702  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3703  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3704  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3705  * objective of this variable is set to zero
3706  */
3707  SCIPlpDecNLoosevars(lp);
3708 
3709  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3710  holelistFree(&var->glbdom.holelist, blkmem);
3711  holelistFree(&var->locdom.holelist, blkmem);
3712  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3713  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3714 
3715  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3716  var->glbdom.lb = fixedval;
3717  var->glbdom.ub = fixedval;
3718  var->locdom.lb = fixedval;
3719  var->locdom.ub = fixedval;
3720 
3721  /* delete implications and variable bounds information */
3722  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3723  assert(var->vlbs == NULL);
3724  assert(var->vubs == NULL);
3725  assert(var->implics == NULL);
3726  assert(var->cliquelist == NULL);
3727 
3728  /* clear the history of the variable */
3729  SCIPhistoryReset(var->history);
3731 
3732  /* convert variable into fixed variable */
3733  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3734 
3735  /* inform problem about the variable's status change */
3736  if( var->probindex != -1 )
3737  {
3738  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3739  }
3740 
3741  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3742  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
3743 
3744  /* issue VARFIXED event */
3745  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3746 
3747  *fixed = TRUE;
3748  break;
3749 
3750  case SCIP_VARSTATUS_COLUMN:
3751  SCIPerrorMessage("cannot fix a column variable\n");
3752  return SCIP_INVALIDDATA;
3753 
3754  case SCIP_VARSTATUS_FIXED:
3755  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3756  SCIPABORT(); /* case is already handled in earlier if condition */
3757  return SCIP_INVALIDDATA; /*lint !e527*/
3758 
3760  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3761  assert(SCIPsetIsZero(set, var->obj));
3762  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3763  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3764  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3765  else
3766  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3767  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3768  branchcand, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3769  break;
3770 
3772  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3773  SCIPABORT();
3774  return SCIP_INVALIDDATA; /*lint !e527*/
3775 
3777  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3778  assert(SCIPsetIsZero(set, var->obj));
3779  assert(var->negatedvar != NULL);
3781  assert(var->negatedvar->negatedvar == var);
3782  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3783  branchcand, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3784  break;
3785 
3786  default:
3787  SCIPerrorMessage("unknown variable status\n");
3788  return SCIP_INVALIDDATA;
3789  }
3790 
3791  return SCIP_OKAY;
3792 }
3793 
3794 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3795  *
3796  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3797  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3798  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3799  *
3800  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3801  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3802  */
3804  SCIP_SET* set, /**< global SCIP settings */
3805  SCIP_VAR** vars, /**< variable array to get active variables */
3806  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3807  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3808  int varssize, /**< available slots in vars and scalars array */
3809  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3810  int* requiredsize, /**< pointer to store the required array size for the active variables */
3811  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3812  )
3813 {
3814  SCIP_VAR** activevars;
3815  SCIP_Real* activescalars;
3816  int nactivevars;
3817  SCIP_Real activeconstant;
3818  SCIP_Bool activeconstantinf;
3819  int activevarssize;
3820 
3821  SCIP_VAR* var;
3822  SCIP_Real scalar;
3823  int v;
3824  int k;
3825 
3826  SCIP_VAR** tmpvars;
3827  SCIP_VAR** multvars;
3828  SCIP_Real* tmpscalars;
3829  SCIP_Real* multscalars;
3830  int tmpvarssize;
3831  int ntmpvars;
3832  int nmultvars;
3833 
3834  SCIP_VAR* multvar;
3835  SCIP_Real multscalar;
3836  SCIP_Real multconstant;
3837  int pos;
3838 
3839  int noldtmpvars;
3840 
3841  SCIP_VAR** tmpvars2;
3842  SCIP_Real* tmpscalars2;
3843  int tmpvarssize2;
3844  int ntmpvars2;
3845 
3846  SCIP_Bool sortagain = FALSE;
3847 
3848  assert(set != NULL);
3849  assert(nvars != NULL);
3850  assert(scalars != NULL || *nvars == 0);
3851  assert(constant != NULL);
3852  assert(requiredsize != NULL);
3853  assert(*nvars <= varssize);
3854 
3855  *requiredsize = 0;
3856 
3857  if( *nvars == 0 )
3858  return SCIP_OKAY;
3859 
3860  assert(vars != NULL);
3861 
3862  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3863  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3864  {
3865  *requiredsize = 1;
3866 
3867  return SCIP_OKAY;
3868  }
3869 
3870  nactivevars = 0;
3871  activeconstant = 0.0;
3872  activeconstantinf = FALSE;
3873  activevarssize = (*nvars) * 2;
3874  ntmpvars = *nvars;
3875  tmpvarssize = *nvars;
3876 
3877  tmpvarssize2 = 1;
3878 
3879  /* allocate temporary memory */
3880  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3881  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3882  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3883  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3884  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3885  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3886 
3887  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3888  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3889  */
3890  for( v = ntmpvars - 1; v >= 0; --v )
3891  {
3892  var = tmpvars[v];
3893  scalar = tmpscalars[v];
3894 
3895  assert(var != NULL);
3896  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3897  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3898  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3899  */
3900  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3901  assert(var != NULL);
3902 
3903  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3904  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3905 
3906  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3907 
3908  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3909  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3912 
3913  tmpvars[v] = var;
3914  tmpscalars[v] = scalar;
3915  }
3916  noldtmpvars = ntmpvars;
3917 
3918  /* sort all variables to combine equal variables easily */
3919  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
3920  ntmpvars = 0;
3921  for( v = 1; v < noldtmpvars; ++v )
3922  {
3923  /* combine same variables */
3924  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
3925  {
3926  tmpscalars[ntmpvars] += tmpscalars[v];
3927  }
3928  else
3929  {
3930  ++ntmpvars;
3931  if( v > ntmpvars )
3932  {
3933  tmpscalars[ntmpvars] = tmpscalars[v];
3934  tmpvars[ntmpvars] = tmpvars[v];
3935  }
3936  }
3937  }
3938  ++ntmpvars;
3939 
3940 #ifdef SCIP_MORE_DEBUG
3941  for( v = 1; v < ntmpvars; ++v )
3942  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
3943 #endif
3944 
3945  /* collect for each variable the representation in active variables */
3946  while( ntmpvars >= 1 )
3947  {
3948  --ntmpvars;
3949  ntmpvars2 = 0;
3950  var = tmpvars[ntmpvars];
3951  scalar = tmpscalars[ntmpvars];
3952 
3953  assert(var != NULL);
3954 
3955  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3956  if( scalar == 0.0 )
3957  continue;
3958 
3959  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3960  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3963 
3964  switch( SCIPvarGetStatus(var) )
3965  {
3966  case SCIP_VARSTATUS_LOOSE:
3967  case SCIP_VARSTATUS_COLUMN:
3968  /* x = a*y + c */
3969  if( nactivevars >= activevarssize )
3970  {
3971  activevarssize *= 2;
3972  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3973  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3974  assert(nactivevars < activevarssize);
3975  }
3976  activevars[nactivevars] = var;
3977  activescalars[nactivevars] = scalar;
3978  nactivevars++;
3979  break;
3980 
3982  /* x = a_1*y_1 + ... + a_n*y_n + c */
3983  nmultvars = var->data.multaggr.nvars;
3984  multvars = var->data.multaggr.vars;
3985  multscalars = var->data.multaggr.scalars;
3986  sortagain = TRUE;
3987 
3988  if( nmultvars + ntmpvars > tmpvarssize )
3989  {
3990  while( nmultvars + ntmpvars > tmpvarssize )
3991  tmpvarssize *= 2;
3992  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3993  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3994  assert(nmultvars + ntmpvars <= tmpvarssize);
3995  }
3996 
3997  if( nmultvars > tmpvarssize2 )
3998  {
3999  while( nmultvars > tmpvarssize2 )
4000  tmpvarssize2 *= 2;
4001  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4002  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4003  assert(nmultvars <= tmpvarssize2);
4004  }
4005 
4006  --nmultvars;
4007 
4008  for( ; nmultvars >= 0; --nmultvars )
4009  {
4010  multvar = multvars[nmultvars];
4011  multscalar = multscalars[nmultvars];
4012  multconstant = 0;
4013 
4014  assert(multvar != NULL);
4015  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4016  assert(multvar != NULL);
4017 
4018  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4019  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4022 
4023  if( !activeconstantinf )
4024  {
4025  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4026 
4027  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4028  {
4029  assert(scalar != 0.0);
4030  if( scalar * multconstant > 0.0 )
4031  {
4032  activeconstant = SCIPsetInfinity(set);
4033  activeconstantinf = TRUE;
4034  }
4035  else
4036  {
4037  activeconstant = -SCIPsetInfinity(set);
4038  activeconstantinf = TRUE;
4039  }
4040  }
4041  else
4042  activeconstant += scalar * multconstant;
4043  }
4044 #ifndef NDEBUG
4045  else
4046  {
4047  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4048  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4049  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4050  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4051  }
4052 #endif
4053 
4054  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4055  {
4056  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4057  tmpscalars[pos] += scalar * multscalar;
4058  }
4059  else
4060  {
4061  tmpvars2[ntmpvars2] = multvar;
4062  tmpscalars2[ntmpvars2] = scalar * multscalar;
4063  ++(ntmpvars2);
4064  assert(ntmpvars2 <= tmpvarssize2);
4065  }
4066  }
4067 
4068  if( ntmpvars2 > 0 )
4069  {
4070  /* sort all variables to combine equal variables easily */
4071  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4072  pos = 0;
4073  for( v = 1; v < ntmpvars2; ++v )
4074  {
4075  /* combine same variables */
4076  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4077  {
4078  tmpscalars2[pos] += tmpscalars2[v];
4079  }
4080  else
4081  {
4082  ++pos;
4083  if( v > pos )
4084  {
4085  tmpscalars2[pos] = tmpscalars2[v];
4086  tmpvars2[pos] = tmpvars2[v];
4087  }
4088  }
4089  }
4090  ntmpvars2 = pos + 1;
4091 #ifdef SCIP_MORE_DEBUG
4092  for( v = 1; v < ntmpvars2; ++v )
4093  {
4094  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4095  }
4096  for( v = 1; v < ntmpvars; ++v )
4097  {
4098  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4099  }
4100 #endif
4101  v = ntmpvars - 1;
4102  k = ntmpvars2 - 1;
4103  pos = ntmpvars + ntmpvars2 - 1;
4104  ntmpvars += ntmpvars2;
4105 
4106  while( v >= 0 && k >= 0 )
4107  {
4108  assert(pos >= 0);
4109  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4110  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4111  {
4112  tmpvars[pos] = tmpvars[v];
4113  tmpscalars[pos] = tmpscalars[v];
4114  --v;
4115  }
4116  else
4117  {
4118  tmpvars[pos] = tmpvars2[k];
4119  tmpscalars[pos] = tmpscalars2[k];
4120  --k;
4121  }
4122  --pos;
4123  assert(pos >= 0);
4124  }
4125  while( v >= 0 )
4126  {
4127  assert(pos >= 0);
4128  tmpvars[pos] = tmpvars[v];
4129  tmpscalars[pos] = tmpscalars[v];
4130  --v;
4131  --pos;
4132  }
4133  while( k >= 0 )
4134  {
4135  assert(pos >= 0);
4136  tmpvars[pos] = tmpvars2[k];
4137  tmpscalars[pos] = tmpscalars2[k];
4138  --k;
4139  --pos;
4140  }
4141  }
4142 #ifdef SCIP_MORE_DEBUG
4143  for( v = 1; v < ntmpvars; ++v )
4144  {
4145  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4146  }
4147 #endif
4148 
4149  if( !activeconstantinf )
4150  {
4151  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4152 
4153  multconstant = SCIPvarGetMultaggrConstant(var);
4154 
4155  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4156  {
4157  assert(scalar != 0.0);
4158  if( scalar * multconstant > 0.0 )
4159  {
4160  activeconstant = SCIPsetInfinity(set);
4161  activeconstantinf = TRUE;
4162  }
4163  else
4164  {
4165  activeconstant = -SCIPsetInfinity(set);
4166  activeconstantinf = TRUE;
4167  }
4168  }
4169  else
4170  activeconstant += scalar * multconstant;
4171  }
4172 #ifndef NDEBUG
4173  else
4174  {
4175  multconstant = SCIPvarGetMultaggrConstant(var);
4176  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4177  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4178  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4179  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4180  }
4181 #endif
4182  break;
4183 
4184  case SCIP_VARSTATUS_FIXED:
4188  default:
4189  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4190  * fixed variables and is handled already
4191  */
4192  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4193  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4194  }
4195  }
4196 
4197  if( mergemultiples )
4198  {
4199  if( sortagain )
4200  {
4201  /* sort variable and scalar array by variable index */
4202  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4203 
4204  /* eliminate duplicates and count required size */
4205  v = nactivevars - 1;
4206  while( v > 0 )
4207  {
4208  /* combine both variable since they are the same */
4209  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4210  {
4211  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4212  {
4213  activescalars[v - 1] += activescalars[v];
4214  --nactivevars;
4215  activevars[v] = activevars[nactivevars];
4216  activescalars[v] = activescalars[nactivevars];
4217  }
4218  else
4219  {
4220  --nactivevars;
4221  activevars[v] = activevars[nactivevars];
4222  activescalars[v] = activescalars[nactivevars];
4223  --nactivevars;
4224  --v;
4225  activevars[v] = activevars[nactivevars];
4226  activescalars[v] = activescalars[nactivevars];
4227  }
4228  }
4229  --v;
4230  }
4231  }
4232  /* the variables were added in reverse order, we revert the order now;
4233  * this should not be necessary, but not doing this changes the behavior sometimes
4234  */
4235  else
4236  {
4237  SCIP_VAR* tmpvar;
4238  SCIP_Real tmpscalar;
4239 
4240  for( v = 0; v < nactivevars / 2; ++v )
4241  {
4242  tmpvar = activevars[v];
4243  tmpscalar = activescalars[v];
4244  activevars[v] = activevars[nactivevars - 1 - v];
4245  activescalars[v] = activescalars[nactivevars - 1 - v];
4246  activevars[nactivevars - 1 - v] = tmpvar;
4247  activescalars[nactivevars - 1 - v] = tmpscalar;
4248  }
4249  }
4250  }
4251  *requiredsize = nactivevars;
4252 
4253  if( varssize >= *requiredsize )
4254  {
4255  assert(vars != NULL);
4256 
4257  *nvars = *requiredsize;
4258 
4259  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4260  {
4261  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4262  if( activeconstantinf )
4263  (*constant) = activeconstant;
4264  else
4265  (*constant) += activeconstant;
4266  }
4267 #ifndef NDEBUG
4268  else
4269  {
4270  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4271  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4272  }
4273 #endif
4274 
4275  /* copy active variable and scalar array to the given arrays */
4276  for( v = 0; v < *nvars; ++v )
4277  {
4278  vars[v] = activevars[v];
4279  scalars[v] = activescalars[v]; /*lint !e613*/
4280  }
4281  }
4282 
4283  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4284  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4285 
4286  SCIPsetFreeBufferArray(set, &tmpscalars);
4287  SCIPsetFreeBufferArray(set, &tmpvars);
4288  SCIPsetFreeBufferArray(set, &activescalars);
4289  SCIPsetFreeBufferArray(set, &activevars);
4290  SCIPsetFreeBufferArray(set, &tmpscalars2);
4291  SCIPsetFreeBufferArray(set, &tmpvars2);
4292 
4293  return SCIP_OKAY;
4294 }
4295 
4296 
4297 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4299  SCIP_VAR* var, /**< problem variable */
4300  BMS_BLKMEM* blkmem, /**< block memory */
4301  SCIP_SET* set /**< global SCIP settings */
4302  )
4303 {
4304  SCIP_Real multconstant;
4305  int multvarssize;
4306  int nmultvars;
4307  int multrequiredsize;
4308 
4309  assert( var != NULL );
4310  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4311  assert(var->scip == set->scip);
4312 
4313  multconstant = var->data.multaggr.constant;
4314  nmultvars = var->data.multaggr.nvars;
4315  multvarssize = var->data.multaggr.varssize;
4316 
4317  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4318 
4319  if( multrequiredsize > multvarssize )
4320  {
4321  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4322  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4323  multvarssize = multrequiredsize;
4324  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4325  assert( multrequiredsize <= multvarssize );
4326  }
4327  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4328  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4329  * may loose performance hereby, since aggregated variables are easier to handle.
4330  *
4331  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4332  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4333  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4334  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4335  *
4336  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4337  *
4338  * The same issue appears in the SCIPvarGetProbvar...() methods.
4339  */
4340 
4341  var->data.multaggr.constant = multconstant;
4342  var->data.multaggr.nvars = nmultvars;
4343  var->data.multaggr.varssize = multvarssize;
4344 
4345  return SCIP_OKAY;
4346 }
4347 
4348 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4349  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4350  * the history merge is reasonable
4351  *
4352  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4353  * this corrupts the variable pseudo costs
4354  * @note Apply with care; no internal checks are performed if the two variables should be merged
4355  */
4357  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4358  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4359  SCIP_STAT* stat /**< problem statistics */
4360  )
4361 {
4362  /* merge only the history of the current run into the target history */
4363  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4364 
4365  /* apply the changes also to the global history */
4366  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4367 }
4368 
4369 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4370  * history over several iterations
4371  */
4372 void SCIPvarSetHistory(
4373  SCIP_VAR* var, /**< variable */
4374  SCIP_HISTORY* history, /**< the history which is to set */
4375  SCIP_STAT* stat /**< problem statistics */
4376  )
4377 {
4378  /* merge only the history of the current run into the target history */
4379  SCIPhistoryUnite(var->history, history, FALSE);
4380 
4381  /* apply the changes also to the global history */
4382  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4383 }
4384 
4385 /** tightens the bounds of both variables in aggregation x = a*y + c */
4386 static
4388  SCIP_VAR* var, /**< problem variable */
4389  BMS_BLKMEM* blkmem, /**< block memory */
4390  SCIP_SET* set, /**< global SCIP settings */
4391  SCIP_STAT* stat, /**< problem statistics */
4392  SCIP_PROB* transprob, /**< tranformed problem data */
4393  SCIP_PROB* origprob, /**< original problem data */
4394  SCIP_PRIMAL* primal, /**< primal data */
4395  SCIP_TREE* tree, /**< branch and bound tree */
4396  SCIP_REOPT* reopt, /**< reoptimization data structure */
4397  SCIP_LP* lp, /**< current LP data */
4398  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4399  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4400  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4401  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4402  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4403  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4404  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4405  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4406  )
4407 {
4408  SCIP_Real varlb;
4409  SCIP_Real varub;
4410  SCIP_Real aggvarlb;
4411  SCIP_Real aggvarub;
4412  SCIP_Bool aggvarbdschanged;
4413 
4414  assert(var != NULL);
4415  assert(var->scip == set->scip);
4416  assert(aggvar != NULL);
4417  assert(!SCIPsetIsZero(set, scalar));
4418  assert(infeasible != NULL);
4419  assert(fixed != NULL);
4420 
4421  *infeasible = FALSE;
4422  *fixed = FALSE;
4423 
4424  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4425  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4426  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4427 
4428  /* loop as long additional changes may be found */
4429  do
4430  {
4431  aggvarbdschanged = FALSE;
4432 
4433  /* update the bounds of the aggregated variable x in x = a*y + c */
4434  if( scalar > 0.0 )
4435  {
4436  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4437  varlb = -SCIPsetInfinity(set);
4438  else
4439  varlb = aggvar->glbdom.lb * scalar + constant;
4440  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4441  varub = SCIPsetInfinity(set);
4442  else
4443  varub = aggvar->glbdom.ub * scalar + constant;
4444  }
4445  else
4446  {
4447  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4448  varub = SCIPsetInfinity(set);
4449  else
4450  varub = aggvar->glbdom.lb * scalar + constant;
4451  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4452  varlb = -SCIPsetInfinity(set);
4453  else
4454  varlb = aggvar->glbdom.ub * scalar + constant;
4455  }
4456  varlb = MAX(varlb, var->glbdom.lb);
4457  varub = MIN(varub, var->glbdom.ub);
4458  SCIPvarAdjustLb(var, set, &varlb);
4459  SCIPvarAdjustUb(var, set, &varub);
4460 
4461  /* check the new bounds */
4462  if( SCIPsetIsGT(set, varlb, varub) )
4463  {
4464  /* the aggregation is infeasible */
4465  *infeasible = TRUE;
4466  return SCIP_OKAY;
4467  }
4468  else if( SCIPsetIsEQ(set, varlb, varub) )
4469  {
4470  /* the aggregated variable is fixed -> fix both variables */
4471  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4472  eventqueue, cliquetable, varlb, infeasible, fixed) );
4473  if( !(*infeasible) )
4474  {
4475  SCIP_Bool aggfixed;
4476 
4477  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4478  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4479  assert(*fixed == aggfixed);
4480  }
4481  return SCIP_OKAY;
4482  }
4483  else
4484  {
4485  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4486  {
4487  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4488  }
4489  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4490  {
4491  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4492  }
4493 
4494  /* update the hole list of the aggregation variable */
4495  /**@todo update hole list of aggregation variable */
4496  }
4497 
4498  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4499  if( scalar > 0.0 )
4500  {
4501  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4502  aggvarlb = -SCIPsetInfinity(set);
4503  else
4504  aggvarlb = (var->glbdom.lb - constant) / scalar;
4505  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4506  aggvarub = SCIPsetInfinity(set);
4507  else
4508  aggvarub = (var->glbdom.ub - constant) / scalar;
4509  }
4510  else
4511  {
4512  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4513  aggvarub = SCIPsetInfinity(set);
4514  else
4515  aggvarub = (var->glbdom.lb - constant) / scalar;
4516  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4517  aggvarlb = -SCIPsetInfinity(set);
4518  else
4519  aggvarlb = (var->glbdom.ub - constant) / scalar;
4520  }
4521  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4522  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4523  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4524  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4525 
4526  /* check the new bounds */
4527  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4528  {
4529  /* the aggregation is infeasible */
4530  *infeasible = TRUE;
4531  return SCIP_OKAY;
4532  }
4533  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4534  {
4535  /* the aggregation variable is fixed -> fix both variables */
4536  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4537  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4538  if( !(*infeasible) )
4539  {
4540  SCIP_Bool varfixed;
4541 
4542  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4543  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4544  assert(*fixed == varfixed);
4545  }
4546  return SCIP_OKAY;
4547  }
4548  else
4549  {
4550  SCIP_Real oldbd;
4551  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4552  {
4553  oldbd = aggvar->glbdom.lb;
4554  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4555  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4556  }
4557  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4558  {
4559  oldbd = aggvar->glbdom.ub;
4560  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4561  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4562  }
4563 
4564  /* update the hole list of the aggregation variable */
4565  /**@todo update hole list of aggregation variable */
4566  }
4567  }
4568  while( aggvarbdschanged );
4569 
4570  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4571  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4572 
4573  return SCIP_OKAY;
4574 }
4575 
4576 /** converts loose variable into aggregated variable */
4578  SCIP_VAR* var, /**< loose problem variable */
4579  BMS_BLKMEM* blkmem, /**< block memory */
4580  SCIP_SET* set, /**< global SCIP settings */
4581  SCIP_STAT* stat, /**< problem statistics */
4582  SCIP_PROB* transprob, /**< tranformed problem data */
4583  SCIP_PROB* origprob, /**< original problem data */
4584  SCIP_PRIMAL* primal, /**< primal data */
4585  SCIP_TREE* tree, /**< branch and bound tree */
4586  SCIP_REOPT* reopt, /**< reoptimization data structure */
4587  SCIP_LP* lp, /**< current LP data */
4588  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4589  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4590  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4591  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4592  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4593  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4594  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4595  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4596  )
4597 {
4598  SCIP_VAR** vars;
4599  SCIP_Real* coefs;
4600  SCIP_Real* constants;
4601  SCIP_Real obj;
4602  SCIP_Real branchfactor;
4603  SCIP_Bool fixed;
4604  int branchpriority;
4605  int nlocksdown[NLOCKTYPES];
4606  int nlocksup[NLOCKTYPES];
4607  int nvbds;
4608  int i;
4609  int j;
4610 
4611  assert(var != NULL);
4612  assert(aggvar != NULL);
4613  assert(var->scip == set->scip);
4614  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4615  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4616  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4617  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4618  assert(infeasible != NULL);
4619  assert(aggregated != NULL);
4620 
4621  /* check aggregation on debugging solution */
4622  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4623 
4624  *infeasible = FALSE;
4625  *aggregated = FALSE;
4626 
4627  /* get active problem variable of aggregation variable */
4628  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4629 
4630  /* aggregation is a fixing, if the scalar is zero */
4631  if( SCIPsetIsZero(set, scalar) )
4632  {
4633  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4634  cliquetable, constant, infeasible, aggregated) );
4635  return SCIP_OKAY;
4636  }
4637 
4638  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4639  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4640  return SCIP_OKAY;
4641 
4642  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4643  * should be changed in the future
4644  */
4645  if( SCIPvarGetHolelistGlobal(var) != NULL )
4646  return SCIP_OKAY;
4647 
4648  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4649  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4650  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4651 
4652  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4653  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4654 
4655  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4656  if( var == aggvar )
4657  {
4658  if( SCIPsetIsEQ(set, scalar, 1.0) )
4659  *infeasible = !SCIPsetIsZero(set, constant);
4660  else
4661  {
4662  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4663  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4664  }
4665  return SCIP_OKAY;
4666  }
4667 
4668  /* tighten the bounds of aggregated and aggregation variable */
4669  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4670  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4671  if( *infeasible || fixed )
4672  {
4673  *aggregated = fixed;
4674  return SCIP_OKAY;
4675  }
4676 
4677  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4678  * aggregated variable
4679  */
4680  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4681  assert(var->cliquelist == NULL);
4682 
4683  /* set the aggregated variable's objective value to 0.0 */
4684  obj = var->obj;
4685  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4686 
4687  /* unlock all locks */
4688  for( i = 0; i < NLOCKTYPES; i++ )
4689  {
4690  nlocksdown[i] = var->nlocksdown[i];
4691  nlocksup[i] = var->nlocksup[i];
4692 
4693  var->nlocksdown[i] = 0;
4694  var->nlocksup[i] = 0;
4695  }
4696 
4697  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4698  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4699  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4700  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4701  {
4702  /* link both variables as negation pair */
4703  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4704  var->data.negate.constant = 1.0;
4705  var->negatedvar = aggvar;
4706  aggvar->negatedvar = var;
4707 
4708  /* copy doNotMultiaggr status */
4709  aggvar->donotmultaggr |= var->donotmultaggr;
4710 
4711  /* mark both variables to be non-deletable */
4713  SCIPvarMarkNotDeletable(aggvar);
4714  }
4715  else
4716  {
4717  /* convert variable into aggregated variable */
4718  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4719  var->data.aggregate.var = aggvar;
4720  var->data.aggregate.scalar = scalar;
4721  var->data.aggregate.constant = constant;
4722 
4723  /* copy doNotMultiaggr status */
4724  aggvar->donotmultaggr |= var->donotmultaggr;
4725 
4726  /* mark both variables to be non-deletable */
4728  SCIPvarMarkNotDeletable(aggvar);
4729  }
4730 
4731  /* make aggregated variable a parent of the aggregation variable */
4732  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4733 
4734  /* relock the variable, thus increasing the locks of the aggregation variable */
4735  for( i = 0; i < NLOCKTYPES; i++ )
4736  {
4737  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4738  }
4739 
4740  /* move the variable bounds to the aggregation variable:
4741  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4742  * - free the variable bounds data structures
4743  */
4744  if( var->vlbs != NULL )
4745  {
4746  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4747  vars = SCIPvboundsGetVars(var->vlbs);
4748  coefs = SCIPvboundsGetCoefs(var->vlbs);
4749  constants = SCIPvboundsGetConstants(var->vlbs);
4750  for( i = 0; i < nvbds && !(*infeasible); ++i )
4751  {
4752  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4753  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4754  }
4755  }
4756  if( var->vubs != NULL )
4757  {
4758  nvbds = SCIPvboundsGetNVbds(var->vubs);
4759  vars = SCIPvboundsGetVars(var->vubs);
4760  coefs = SCIPvboundsGetCoefs(var->vubs);
4761  constants = SCIPvboundsGetConstants(var->vubs);
4762  for( i = 0; i < nvbds && !(*infeasible); ++i )
4763  {
4764  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4765  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4766  }
4767  }
4768  SCIPvboundsFree(&var->vlbs, blkmem);
4769  SCIPvboundsFree(&var->vubs, blkmem);
4770 
4771  /* move the implications to the aggregation variable:
4772  * - add all implications again to the variable, thus adding it to the aggregation variable
4773  * - free the implications data structures
4774  */
4775  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4776  {
4777  assert(SCIPvarIsBinary(var));
4778  for( i = 0; i < 2; ++i )
4779  {
4780  SCIP_VAR** implvars;
4781  SCIP_BOUNDTYPE* impltypes;
4782  SCIP_Real* implbounds;
4783  int nimpls;
4784 
4785  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4786  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4787  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4788  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4789 
4790  for( j = 0; j < nimpls && !(*infeasible); ++j )
4791  {
4792  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4793  * implication to the aggregated variable?
4794  */
4795  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4796  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4797  NULL) );
4798  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4799  }
4800  }
4801  }
4802  SCIPimplicsFree(&var->implics, blkmem);
4803 
4804  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4805  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4806  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4807  SCIPhistoryReset(var->history);
4809 
4810  /* update flags of aggregation variable */
4811  aggvar->removable &= var->removable;
4812 
4813  /* update branching factors and priorities of both variables to be the maximum of both variables */
4814  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4815  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4816  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4817  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4818  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4819  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4820 
4821  /* update branching direction of both variables to agree to a single direction */
4822  if( scalar >= 0.0 )
4823  {
4825  {
4827  }
4828  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4829  {
4831  }
4832  else if( var->branchdirection != aggvar->branchdirection )
4833  {
4835  }
4836  }
4837  else
4838  {
4840  {
4842  }
4843  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4844  {
4846  }
4847  else if( var->branchdirection != aggvar->branchdirection )
4848  {
4850  }
4851  }
4852 
4853  if( var->probindex != -1 )
4854  {
4855  /* inform problem about the variable's status change */
4856  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4857  }
4858 
4859  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4860  * variable and the problem's objective offset
4861  */
4862  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4863 
4864  /* issue VARFIXED event */
4865  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4866 
4867  *aggregated = TRUE;
4868 
4869  return SCIP_OKAY;
4870 }
4871 
4872 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4873  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4874  *
4875  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4876  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4877  */
4878 static
4880  SCIP_SET* set, /**< global SCIP settings */
4881  BMS_BLKMEM* blkmem, /**< block memory */
4882  SCIP_STAT* stat, /**< problem statistics */
4883  SCIP_PROB* transprob, /**< tranformed problem data */
4884  SCIP_PROB* origprob, /**< original problem data */
4885  SCIP_PRIMAL* primal, /**< primal data */
4886  SCIP_TREE* tree, /**< branch and bound tree */
4887  SCIP_REOPT* reopt, /**< reoptimization data structure */
4888  SCIP_LP* lp, /**< current LP data */
4889  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4890  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4891  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4892  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4893  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4894  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4895  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4896  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4897  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4898  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4899  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4900  )
4901 {
4902  SCIP_VAR* aggvar;
4903  char aggvarname[SCIP_MAXSTRLEN];
4904  SCIP_Longint scalarxn = 0;
4905  SCIP_Longint scalarxd = 0;
4906  SCIP_Longint scalaryn = 0;
4907  SCIP_Longint scalaryd = 0;
4908  SCIP_Longint a;
4909  SCIP_Longint b;
4910  SCIP_Longint c;
4911  SCIP_Longint scm;
4912  SCIP_Longint gcd;
4913  SCIP_Longint currentclass;
4914  SCIP_Longint classstep;
4915  SCIP_Longint xsol;
4916  SCIP_Longint ysol;
4917  SCIP_Bool success;
4918  SCIP_VARTYPE vartype;
4919 
4920 #define MAXDNOM 1000000LL
4921 
4922  assert(set != NULL);
4923  assert(blkmem != NULL);
4924  assert(stat != NULL);
4925  assert(transprob != NULL);
4926  assert(origprob != NULL);
4927  assert(tree != NULL);
4928  assert(lp != NULL);
4929  assert(cliquetable != NULL);
4930  assert(branchcand != NULL);
4931  assert(eventqueue != NULL);
4932  assert(varx != NULL);
4933  assert(vary != NULL);
4934  assert(varx != vary);
4935  assert(infeasible != NULL);
4936  assert(aggregated != NULL);
4937  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4938  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4940  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4942  assert(!SCIPsetIsZero(set, scalarx));
4943  assert(!SCIPsetIsZero(set, scalary));
4944 
4945  *infeasible = FALSE;
4946  *aggregated = FALSE;
4947 
4948  /* get rational representation of coefficients */
4949  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4950  if( success )
4951  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4952  if( !success )
4953  return SCIP_OKAY;
4954  assert(scalarxd >= 1);
4955  assert(scalaryd >= 1);
4956 
4957  /* multiply equality with smallest common denominator */
4958  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4959  a = (scm/scalarxd)*scalarxn;
4960  b = (scm/scalaryd)*scalaryn;
4961  rhs *= scm;
4962 
4963  /* divide equality by the greatest common divisor of a and b */
4964  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4965  a /= gcd;
4966  b /= gcd;
4967  rhs /= gcd;
4968  assert(a != 0);
4969  assert(b != 0);
4970 
4971  /* check, if right hand side is integral */
4972  if( !SCIPsetIsFeasIntegral(set, rhs) )
4973  {
4974  *infeasible = TRUE;
4975  return SCIP_OKAY;
4976  }
4977  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4978 
4979  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
4980  return SCIP_OKAY;
4981 
4982  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4983  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4984  {
4985  /* aggregate x = - b/a*y + c/a */
4986  /*lint --e{653}*/
4987  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4988  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4989  assert(*aggregated);
4990  return SCIP_OKAY;
4991  }
4992  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4993  {
4994  /* aggregate y = - a/b*x + c/b */
4995  /*lint --e{653}*/
4996  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4997  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4998  assert(*aggregated);
4999  return SCIP_OKAY;
5000  }
5001 
5002  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5003  * common divisor. Let (x',y') be a solution of the equality
5004  * a*x + b*y == c -> a*x == c - b*y
5005  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5006  */
5007 
5008  /* find initial solution (x',y'):
5009  * - find y' such that c - b*y' is a multiple of a
5010  * - start in equivalence class c%a
5011  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5012  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5013  * - 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
5014  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5015  *
5016  * Algorithm works for a > 0 only.
5017  */
5018  if( a < 0 )
5019  {
5020  a = -a;
5021  b = -b;
5022  c = -c;
5023  }
5024  assert(0 <= a);
5025 
5026  /* search upwards from ysol = 0 */
5027  ysol = 0;
5028  currentclass = c%a;
5029  if( currentclass < 0 )
5030  currentclass += a;
5031  assert(0 <= currentclass && currentclass < a);
5032 
5033  classstep = (-b)%a;
5034 
5035  if( classstep < 0 )
5036  classstep += a;
5037  assert(0 <= classstep && classstep < a);
5038 
5039  while( currentclass != 0 )
5040  {
5041  assert(0 <= currentclass && currentclass < a);
5042  currentclass += classstep;
5043  if( currentclass >= a )
5044  currentclass -= a;
5045  ysol++;
5046  }
5047  assert(ysol < a);
5048  assert(((c - b*ysol)%a) == 0);
5049 
5050  xsol = (c - b*ysol)/a;
5051 
5052  /* determine variable type for new artificial variable:
5053  *
5054  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5055  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5056  * integral type
5057  */
5060 
5061  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5062  * - create new integer variable z with infinite bounds
5063  * - aggregate variable x = -b*z + x'
5064  * - aggregate variable y = a*z + y'
5065  * - the bounds of z are calculated automatically during aggregation
5066  */
5067  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5068  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5069  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5071  NULL, NULL, NULL, NULL, NULL) );
5072 
5073  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5074 
5075  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5076  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5077  assert(*aggregated || *infeasible);
5078 
5079  if( !(*infeasible) )
5080  {
5081  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5082  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5083  assert(*aggregated || *infeasible);
5084  }
5085 
5086  /* release z */
5087  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5088 
5089  return SCIP_OKAY;
5090 }
5091 
5092 /** performs second step of SCIPaggregateVars():
5093  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5094  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5095  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5096  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5097  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5098  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5099  *
5100  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5101  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5102  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5103  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5104  */
5106  SCIP_SET* set, /**< global SCIP settings */
5107  BMS_BLKMEM* blkmem, /**< block memory */
5108  SCIP_STAT* stat, /**< problem statistics */
5109  SCIP_PROB* transprob, /**< tranformed problem data */
5110  SCIP_PROB* origprob, /**< original problem data */
5111  SCIP_PRIMAL* primal, /**< primal data */
5112  SCIP_TREE* tree, /**< branch and bound tree */
5113  SCIP_REOPT* reopt, /**< reoptimization data structure */
5114  SCIP_LP* lp, /**< current LP data */
5115  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5116  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5117  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5118  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5119  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5120  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5121  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5122  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5123  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5124  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5125  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5126  )
5127 {
5128  SCIP_Bool easyaggr;
5129  SCIP_Real maxscalar;
5130  SCIP_Real absquot;
5131 
5132  assert(set != NULL);
5133  assert(blkmem != NULL);
5134  assert(stat != NULL);
5135  assert(transprob != NULL);
5136  assert(origprob != NULL);
5137  assert(tree != NULL);
5138  assert(lp != NULL);
5139  assert(cliquetable != NULL);
5140  assert(branchcand != NULL);
5141  assert(eventqueue != NULL);
5142  assert(varx != NULL);
5143  assert(vary != NULL);
5144  assert(varx != vary);
5145  assert(infeasible != NULL);
5146  assert(aggregated != NULL);
5147  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5148  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5149  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5150  assert(!SCIPsetIsZero(set, scalarx));
5151  assert(!SCIPsetIsZero(set, scalary));
5152 
5153  *infeasible = FALSE;
5154  *aggregated = FALSE;
5155 
5156  absquot = REALABS(scalarx / scalary);
5157  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5158  maxscalar = MAX(maxscalar, 1.0);
5159 
5160  if( absquot > maxscalar || absquot < 1 / maxscalar )
5161  return SCIP_OKAY;
5162 
5163  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5164  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5165  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5166  {
5167  SCIP_VAR* var;
5168  SCIP_Real scalar;
5169 
5170  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5171  var = vary;
5172  vary = varx;
5173  varx = var;
5174  scalar = scalary;
5175  scalary = scalarx;
5176  scalarx = scalar;
5177  }
5178 
5179  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5180  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5181  return SCIP_OKAY;
5182 
5183  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5184 
5185  /* figure out, which variable should be aggregated */
5186  easyaggr = FALSE;
5187 
5188  /* check if it is an easy aggregation that means:
5189  *
5190  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5191  */
5192  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5193  {
5195  {
5196  easyaggr = TRUE;
5197  }
5198  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5199  {
5200  easyaggr = TRUE;
5201  }
5202  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5203  {
5204  /* we have an easy aggregation if we flip the variables x and y */
5205  SCIP_VAR* var;
5206  SCIP_Real scalar;
5207 
5208  /* switch the variables, such that varx is the aggregated variable */
5209  var = vary;
5210  vary = varx;
5211  varx = var;
5212  scalar = scalary;
5213  scalary = scalarx;
5214  scalarx = scalar;
5215  easyaggr = TRUE;
5216  }
5217  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5218  {
5219  /* the aggregation is still easy if both variables are continuous */
5220  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5221  easyaggr = TRUE;
5222  }
5223  }
5224 
5225  /* did we find an "easy" aggregation? */
5226  if( easyaggr )
5227  {
5228  SCIP_Real scalar;
5229  SCIP_Real constant;
5230 
5231  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5232 
5233  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5234  scalar = -scalary/scalarx;
5235  constant = rhs/scalarx;
5236 
5237  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5238  return SCIP_OKAY;
5239 
5240  /* check aggregation for integer feasibility */
5243  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5244  {
5245  *infeasible = TRUE;
5246  return SCIP_OKAY;
5247  }
5248 
5249  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5250  * since then we would loose the corresponding divisibility property
5251  */
5252  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5253 
5254  /* aggregate the variable */
5255  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5256  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5257  assert(*aggregated || *infeasible);
5258  }
5261  {
5262  /* the variables are both integral: we have to try to find an integer aggregation */
5263  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5264  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5265  }
5266 
5267  return SCIP_OKAY;
5268 }
5269 
5270 /** converts variable into multi-aggregated variable */
5272  SCIP_VAR* var, /**< problem variable */
5273  BMS_BLKMEM* blkmem, /**< block memory */
5274  SCIP_SET* set, /**< global SCIP settings */
5275  SCIP_STAT* stat, /**< problem statistics */
5276  SCIP_PROB* transprob, /**< tranformed problem data */
5277  SCIP_PROB* origprob, /**< original problem data */
5278  SCIP_PRIMAL* primal, /**< primal data */
5279  SCIP_TREE* tree, /**< branch and bound tree */
5280  SCIP_REOPT* reopt, /**< reoptimization data structure */
5281  SCIP_LP* lp, /**< current LP data */
5282  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5283  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5284  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5285  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5286  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5287  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5288  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5289  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5290  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5291  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5292  )
5293 {
5294  SCIP_VAR** tmpvars;
5295  SCIP_Real* tmpscalars;
5296  SCIP_Real obj;
5297  SCIP_Real branchfactor;
5298  int branchpriority;
5299  SCIP_BRANCHDIR branchdirection;
5300  int nlocksdown[NLOCKTYPES];
5301  int nlocksup[NLOCKTYPES];
5302  int v;
5303  SCIP_Real tmpconstant;
5304  SCIP_Real tmpscalar;
5305  int ntmpvars;
5306  int tmpvarssize;
5307  int tmprequiredsize;
5308  int i;
5309 
5310  assert(var != NULL);
5311  assert(var->scip == set->scip);
5312  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5313  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5314  assert(naggvars == 0 || aggvars != NULL);
5315  assert(naggvars == 0 || scalars != NULL);
5316  assert(infeasible != NULL);
5317  assert(aggregated != NULL);
5318 
5319  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5320 
5321  /* check multi-aggregation on debugging solution */
5322  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5323 
5324  *infeasible = FALSE;
5325  *aggregated = FALSE;
5326 
5327  switch( SCIPvarGetStatus(var) )
5328  {
5330  if( var->data.original.transvar == NULL )
5331  {
5332  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5333  return SCIP_INVALIDDATA;
5334  }
5335  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5336  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5337  break;
5338 
5339  case SCIP_VARSTATUS_LOOSE:
5340  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5341 
5342  /* check if we would create a self-reference */
5343  ntmpvars = naggvars;
5344  tmpvarssize = naggvars;
5345  tmpconstant = constant;
5346  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5347  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5348 
5349  /* get all active variables for multi-aggregation */
5350  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5351  if( tmprequiredsize > tmpvarssize )
5352  {
5353  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5354  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5355  tmpvarssize = tmprequiredsize;
5356  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5357  assert( tmprequiredsize <= tmpvarssize );
5358  }
5359 
5360  tmpscalar = 0.0;
5361 
5362  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5363  * possible multi-aggregated variable
5364  */
5365  for( v = ntmpvars - 1; v >= 0; --v )
5366  {
5367  assert(tmpvars[v] != NULL);
5368  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5369 
5370  if( tmpvars[v]->index == var->index )
5371  {
5372  tmpscalar += tmpscalars[v];
5373  tmpvars[v] = tmpvars[ntmpvars - 1];
5374  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5375  --ntmpvars;
5376  }
5377  }
5378 
5379  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5380  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5381  {
5382  if( ntmpvars == 0 )
5383  {
5384  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5385  {
5386  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5387  goto TERMINATE;
5388  }
5389  else /* 0 = c and c != 0 */
5390  {
5391  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5392  *infeasible = TRUE;
5393  goto TERMINATE;
5394  }
5395  }
5396  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5397  {
5398  assert(tmpscalars[0] != 0.0);
5399  assert(tmpvars[0] != NULL);
5400 
5401  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5402  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5403  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5404  goto TERMINATE;
5405  }
5406  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 */
5407  {
5408  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5409 
5410  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5411  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5412 
5413  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5414  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5415  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5416 
5417  goto TERMINATE;
5418  }
5419  else
5420  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5421  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5422  */
5423  goto TERMINATE;
5424  }
5425  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5426  else if( !SCIPsetIsZero(set, tmpscalar) )
5427  {
5428  tmpscalar = 1 - tmpscalar;
5429  tmpconstant /= tmpscalar;
5430  for( v = ntmpvars - 1; v >= 0; --v )
5431  tmpscalars[v] /= tmpscalar;
5432  }
5433 
5434  /* check, if we are in one of the simple cases */
5435  if( ntmpvars == 0 )
5436  {
5437  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5438  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5439  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5440  goto TERMINATE;
5441  }
5442 
5443  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5444  if( ntmpvars == 1 )
5445  {
5446  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5447  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5448 
5449  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5450  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5451  infeasible, aggregated) );
5452 
5453  goto TERMINATE;
5454  }
5455 
5456  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5457  * empty hole list; this should be changed in the future */
5458  if( SCIPvarGetHolelistGlobal(var) != NULL )
5459  goto TERMINATE;
5460 
5461  /* if the variable is not allowed to be multi-aggregated */
5462  if( SCIPvarDoNotMultaggr(var) )
5463  {
5464  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5465  goto TERMINATE;
5466  }
5467 
5468  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5469  * variable bound variable of another variable), we have to remove it from the other variables implications or
5470  * variable bounds
5471  */
5472  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5473  assert(var->vlbs == NULL);
5474  assert(var->vubs == NULL);
5475  assert(var->implics == NULL);
5476  assert(var->cliquelist == NULL);
5477 
5478  /* set the aggregated variable's objective value to 0.0 */
5479  obj = var->obj;
5480  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5481 
5482  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5483  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5484  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5485  * objective of this variable is set to zero
5486  */
5487  SCIPlpDecNLoosevars(lp);
5488 
5489  /* unlock all rounding locks */
5490  for( i = 0; i < NLOCKTYPES; i++ )
5491  {
5492  nlocksdown[i] = var->nlocksdown[i];
5493  nlocksup[i] = var->nlocksup[i];
5494 
5495  var->nlocksdown[i] = 0;
5496  var->nlocksup[i] = 0;
5497  }
5498 
5499  /* convert variable into multi-aggregated variable */
5500  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5501  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5502  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5503  var->data.multaggr.constant = tmpconstant;
5504  var->data.multaggr.nvars = ntmpvars;
5505  var->data.multaggr.varssize = ntmpvars;
5506 
5507  /* mark variable to be non-deletable */
5509 
5510  /* relock the variable, thus increasing the locks of the aggregation variables */
5511  for( i = 0; i < NLOCKTYPES; i++ )
5512  {
5513  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5514  }
5515 
5516  /* update flags and branching factors and priorities of aggregation variables;
5517  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5518  */
5519  branchfactor = var->branchfactor;
5520  branchpriority = var->branchpriority;
5521  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5522 
5523  for( v = 0; v < ntmpvars; ++v )
5524  {
5525  assert(tmpvars[v] != NULL);
5526  tmpvars[v]->removable &= var->removable;
5527  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5528  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5529 
5530  /* mark variable to be non-deletable */
5531  SCIPvarMarkNotDeletable(tmpvars[v]);
5532  }
5533  for( v = 0; v < ntmpvars; ++v )
5534  {
5535  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5536  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5537  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5538  {
5539  if( tmpscalars[v] >= 0.0 )
5540  {
5541  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5542  }
5543  else
5544  {
5545  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5546  }
5547  }
5548  }
5549  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5550  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5551 
5552  if( var->probindex != -1 )
5553  {
5554  /* inform problem about the variable's status change */
5555  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5556  }
5557 
5558  /* issue VARFIXED event */
5559  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5560 
5561  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5562  * variables and the problem's objective offset
5563  */
5564  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5565 
5566  *aggregated = TRUE;
5567 
5568  TERMINATE:
5569  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5570  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5571 
5572  break;
5573 
5574  case SCIP_VARSTATUS_COLUMN:
5575  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5576  return SCIP_INVALIDDATA;
5577 
5578  case SCIP_VARSTATUS_FIXED:
5579  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5580  return SCIP_INVALIDDATA;
5581 
5583  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5584  return SCIP_INVALIDDATA;
5585 
5587  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5588  return SCIP_INVALIDDATA;
5589 
5591  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5592  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5593  */
5594  assert(SCIPsetIsZero(set, var->obj));
5595  assert(var->negatedvar != NULL);
5597  assert(var->negatedvar->negatedvar == var);
5598 
5599  /* switch the signs of the aggregation scalars */
5600  for( v = 0; v < naggvars; ++v )
5601  scalars[v] *= -1.0;
5602 
5603  /* perform the multi aggregation on the negation variable */
5604  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5605  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5606  var->data.negate.constant - constant, infeasible, aggregated) );
5607 
5608  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5609  for( v = 0; v < naggvars; ++v )
5610  scalars[v] *= -1.0;
5611  break;
5612 
5613  default:
5614  SCIPerrorMessage("unknown variable status\n");
5615  return SCIP_INVALIDDATA;
5616  }
5617 
5618  return SCIP_OKAY;
5619 }
5620 
5621 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5622  * or for original variables the same variable is returned
5623  */
5624 static
5626  SCIP_VAR* var /**< problem variable */
5627  )
5628 {
5629  SCIP_VAR* retvar;
5630 
5631  assert(var != NULL);
5632 
5633  retvar = var;
5634 
5635  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5636 
5637  while( TRUE ) /*lint !e716 */
5638  {
5639  assert(retvar != NULL);
5640 
5641  switch( SCIPvarGetStatus(retvar) )
5642  {
5644  case SCIP_VARSTATUS_LOOSE:
5645  case SCIP_VARSTATUS_COLUMN:
5646  case SCIP_VARSTATUS_FIXED:
5647  return retvar;
5648 
5650  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5651  if ( retvar->data.multaggr.nvars == 1 )
5652  retvar = retvar->data.multaggr.vars[0];
5653  else
5654  return retvar;
5655  break;
5656 
5658  retvar = retvar->data.aggregate.var;
5659  break;
5660 
5662  retvar = retvar->negatedvar;
5663  break;
5664 
5665  default:
5666  SCIPerrorMessage("unknown variable status\n");
5667  SCIPABORT();
5668  return NULL; /*lint !e527*/
5669  }
5670  }
5671 }
5672 
5673 /** returns whether variable is not allowed to be multi-aggregated */
5675  SCIP_VAR* var /**< problem variable */
5676  )
5677 {
5678  SCIP_VAR* retvar;
5679 
5680  assert(var != NULL);
5681 
5682  retvar = varGetActiveVar(var);
5683  assert(retvar != NULL);
5684 
5685  switch( SCIPvarGetStatus(retvar) )
5686  {
5688  case SCIP_VARSTATUS_LOOSE:
5689  case SCIP_VARSTATUS_COLUMN:
5690  case SCIP_VARSTATUS_FIXED:
5691  return retvar->donotmultaggr;
5692 
5694  return FALSE;
5695 
5698  default:
5699  SCIPerrorMessage("wrong variable status\n");
5700  SCIPABORT();
5701  return FALSE; /*lint !e527 */
5702  }
5703 }
5704 
5705 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5706  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5707  * negated variable is created
5708  */
5710  SCIP_VAR* var, /**< problem variable to negate */
5711  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5712  SCIP_SET* set, /**< global SCIP settings */
5713  SCIP_STAT* stat, /**< problem statistics */
5714  SCIP_VAR** negvar /**< pointer to store the negated variable */
5715  )
5716 {
5717  assert(var != NULL);
5718  assert(var->scip == set->scip);
5719  assert(negvar != NULL);
5720 
5721  /* check, if we already created the negated variable */
5722  if( var->negatedvar == NULL )
5723  {
5724  char negvarname[SCIP_MAXSTRLEN];
5725 
5726  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5727 
5728  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5729 
5730  /* negation is only possible for bounded variables */
5731  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5732  {
5733  SCIPerrorMessage("cannot negate unbounded variable\n");
5734  return SCIP_INVALIDDATA;
5735  }
5736 
5737  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5738 
5739  /* create negated variable */
5740  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5741  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5742  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5743  if( SCIPvarIsBinary(var) )
5744  (*negvar)->data.negate.constant = 1.0;
5745  else
5746  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5747 
5748  /* create event filter for transformed variable */
5749  if( SCIPvarIsTransformed(var) )
5750  {
5751  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5752  }
5753 
5754  /* set the bounds corresponding to the negation variable */
5755  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5756  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5757  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5758  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5759  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5760 
5761  /* link the variables together */
5762  var->negatedvar = *negvar;
5763  (*negvar)->negatedvar = var;
5764 
5765  /* mark both variables to be non-deletable */
5767  SCIPvarMarkNotDeletable(*negvar);
5768 
5769  /* copy the branch factor and priority, and use the negative preferred branching direction */
5770  (*negvar)->branchfactor = var->branchfactor;
5771  (*negvar)->branchpriority = var->branchpriority;
5772  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5773 
5774  /* copy doNotMultiaggr status */
5775  (*negvar)->donotmultaggr = var->donotmultaggr;
5776 
5777  /* copy lazy bounds (they have to be flipped) */
5778  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5779  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5780 
5781  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5782  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5783  assert((*negvar)->nuses == 1);
5784  }
5785  assert(var->negatedvar != NULL);
5786 
5787  /* return the negated variable */
5788  *negvar = var->negatedvar;
5789 
5790  /* exactly one variable of the negation pair has to be marked as negated variable */
5792 
5793  return SCIP_OKAY;
5794 }
5795 
5796 /** informs variable that its position in problem's vars array changed */
5797 static
5798 void varSetProbindex(
5799  SCIP_VAR* var, /**< problem variable */
5800  int probindex /**< new problem index of variable (-1 for removal) */
5801  )
5802 {
5803  assert(var != NULL);
5804  assert(probindex >= 0 || var->vlbs == NULL);
5805  assert(probindex >= 0 || var->vubs == NULL);
5806  assert(probindex >= 0 || var->implics == NULL);
5807 
5808  var->probindex = probindex;
5810  {
5811  assert(var->data.col != NULL);
5812  var->data.col->var_probindex = probindex;
5813  }
5814 }
5815 
5816 /** informs variable that its position in problem's vars array changed */
5817 void SCIPvarSetProbindex(
5818  SCIP_VAR* var, /**< problem variable */
5819  int probindex /**< new problem index of variable */
5820  )
5821 {
5822  assert(var != NULL);
5823  assert(probindex >= 0);
5824 
5825  varSetProbindex(var, probindex);
5826 }
5827 
5828 /** gives the variable a new name
5829  *
5830  * @note the old pointer is overwritten, which might result in a memory leakage
5831  */
5833  SCIP_VAR* var, /**< problem variable */
5834  const char* name /**< new name of variable */
5835  )
5836 {
5837  assert(var != NULL);
5838  assert(name != NULL);
5839 
5840  var->name = (char*)name;
5841 }
5842 
5843 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5844  * implication graph;
5845  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5846  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5847  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5848  * than removing the variables one by one, each time updating all lists of the other variables.
5849  */
5851  SCIP_VAR* var, /**< problem variable */
5852  BMS_BLKMEM* blkmem, /**< block memory buffer */
5853  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5854  SCIP_SET* set, /**< global SCIP settings */
5855  SCIP_Bool final /**< is this the final removal of all problem variables? */
5856  )
5857 {
5858  assert(SCIPvarGetProbindex(var) >= 0);
5859  assert(var->scip == set->scip);
5860 
5861  /* if the variable is active in the transformed problem, remove it from the implication graph */
5862  if( SCIPvarIsTransformed(var)
5864  {
5865  if( final )
5866  {
5867  /* just destroy the data structures */
5868  SCIPvboundsFree(&var->vlbs, blkmem);
5869  SCIPvboundsFree(&var->vubs, blkmem);
5870  SCIPimplicsFree(&var->implics, blkmem);
5871  }
5872  else
5873  {
5874  /* unlink the variable from all other variables' lists and free the data structures */
5875  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5876  }
5877  }
5878 
5879  /* mark the variable to be no longer a member of the problem */
5880  varSetProbindex(var, -1);
5881 
5882  return SCIP_OKAY;
5883 }
5884 
5885 /** marks the variable to be deleted from the problem */
5886 void SCIPvarMarkDeleted(
5887  SCIP_VAR* var /**< problem variable */
5888  )
5889 {
5890  assert(var != NULL);
5891  assert(var->probindex != -1);
5892 
5893  var->deleted = TRUE;
5894 }
5895 
5896 /** marks the variable to not to be multi-aggregated */
5898  SCIP_VAR* var /**< problem variable */
5899  )
5900 {
5901  SCIP_VAR* retvar;
5902 
5903  assert(var != NULL);
5904 
5905  retvar = varGetActiveVar(var);
5906  assert(retvar != NULL);
5907 
5908  switch( SCIPvarGetStatus(retvar) )
5909  {
5911  case SCIP_VARSTATUS_LOOSE:
5912  case SCIP_VARSTATUS_COLUMN:
5913  case SCIP_VARSTATUS_FIXED:
5914  retvar->donotmultaggr = TRUE;
5915  break;
5916 
5918  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5919  return SCIP_INVALIDDATA;
5920 
5923  default:
5924  SCIPerrorMessage("wrong variable status\n");
5925  return SCIP_INVALIDDATA;
5926  }
5927 
5928  return SCIP_OKAY;
5929 }
5930 
5931 /** changes type of variable; cannot be called, if var belongs to a problem */
5933  SCIP_VAR* var, /**< problem variable to change */
5934  SCIP_VARTYPE vartype /**< new type of variable */
5935  )
5936 {
5937  assert(var != NULL);
5938 
5939  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5940 
5941  if( var->probindex >= 0 )
5942  {
5943  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5944  return SCIP_INVALIDDATA;
5945  }
5946 
5947  var->vartype = vartype; /*lint !e641*/
5948  if( var->negatedvar != NULL )
5949  var->negatedvar->vartype = vartype; /*lint !e641*/
5950 
5951  return SCIP_OKAY;
5952 }
5953 
5954 /** appends OBJCHANGED event to the event queue */
5955 static
5957  SCIP_VAR* var, /**< problem variable to change */
5958  BMS_BLKMEM* blkmem, /**< block memory */
5959  SCIP_SET* set, /**< global SCIP settings */
5960  SCIP_PRIMAL* primal, /**< primal data */
5961  SCIP_LP* lp, /**< current LP data */
5962  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5963  SCIP_Real oldobj, /**< old objective value for variable */
5964  SCIP_Real newobj /**< new objective value for variable */
5965  )
5966 {
5967  SCIP_EVENT* event;
5968 
5969  assert(var != NULL);
5970  assert(var->scip == set->scip);
5971  assert(var->eventfilter != NULL);
5973  assert(SCIPvarIsTransformed(var));
5974  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5975 
5976  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5977  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5978 
5979  return SCIP_OKAY;
5980 }
5981 
5982 /** changes objective value of variable */
5984  SCIP_VAR* var, /**< variable to change */
5985  BMS_BLKMEM* blkmem, /**< block memory */
5986  SCIP_SET* set, /**< global SCIP settings */
5987  SCIP_PROB* prob, /**< problem data */
5988  SCIP_PRIMAL* primal, /**< primal data */
5989  SCIP_LP* lp, /**< current LP data */
5990  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5991  SCIP_Real newobj /**< new objective value for variable */
5992  )
5993 {
5994  SCIP_Real oldobj;
5995 
5996  assert(var != NULL);
5997  assert(set != NULL);
5998  assert(var->scip == set->scip);
5999 
6000  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6001 
6002  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6003  {
6004  switch( SCIPvarGetStatus(var) )
6005  {
6007  if( var->data.original.transvar != NULL )
6008  {
6009  assert(SCIPprobIsTransformed(prob));
6010 
6011  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6012  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6013  }
6014  else
6015  assert(set->stage == SCIP_STAGE_PROBLEM);
6016 
6017  var->obj = newobj;
6018  var->unchangedobj = newobj;
6019 
6020  break;
6021 
6022  case SCIP_VARSTATUS_LOOSE:
6023  case SCIP_VARSTATUS_COLUMN:
6024  oldobj = var->obj;
6025  var->obj = newobj;
6026 
6027  /* update unchanged objective value of variable */
6028  if( !lp->divingobjchg )
6029  var->unchangedobj = newobj;
6030 
6031  /* update the number of variables with non-zero objective coefficient;
6032  * we only want to do the update, if the variable is added to the problem;
6033  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6034  */
6035  if( SCIPvarIsActive(var) )
6036  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6037 
6038  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6039  break;
6040 
6041  case SCIP_VARSTATUS_FIXED:
6045  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6046  return SCIP_INVALIDDATA;
6047 
6048  default:
6049  SCIPerrorMessage("unknown variable status\n");
6050  return SCIP_INVALIDDATA;
6051  }
6052  }
6053 
6054  return SCIP_OKAY;
6055 }
6056 
6057 /** adds value to objective value of variable */
6059  SCIP_VAR* var, /**< variable to change */
6060  BMS_BLKMEM* blkmem, /**< block memory */
6061  SCIP_SET* set, /**< global SCIP settings */
6062  SCIP_STAT* stat, /**< problem statistics */
6063  SCIP_PROB* transprob, /**< transformed problem data */
6064  SCIP_PROB* origprob, /**< original problem data */
6065  SCIP_PRIMAL* primal, /**< primal data */
6066  SCIP_TREE* tree, /**< branch and bound tree */
6067  SCIP_REOPT* reopt, /**< reoptimization data structure */
6068  SCIP_LP* lp, /**< current LP data */
6069  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6070  SCIP_Real addobj /**< additional objective value for variable */
6071  )
6072 {
6073  assert(var != NULL);
6074  assert(set != NULL);
6075  assert(var->scip == set->scip);
6076  assert(set->stage < SCIP_STAGE_INITSOLVE);
6077 
6078  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6079 
6080  if( !SCIPsetIsZero(set, addobj) )
6081  {
6082  SCIP_Real oldobj;
6083  int i;
6084 
6085  switch( SCIPvarGetStatus(var) )
6086  {
6088  if( var->data.original.transvar != NULL )
6089  {
6090  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6091  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6092  }
6093  else
6094  assert(set->stage == SCIP_STAGE_PROBLEM);
6095 
6096  var->obj += addobj;
6097  var->unchangedobj += addobj;
6098  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6099 
6100  break;
6101 
6102  case SCIP_VARSTATUS_LOOSE:
6103  case SCIP_VARSTATUS_COLUMN:
6104  oldobj = var->obj;
6105  var->obj += addobj;
6106 
6107  /* update unchanged objective value of variable */
6108  if( !lp->divingobjchg )
6109  {
6110  var->unchangedobj += addobj;
6111  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6112  }
6113 
6114  /* update the number of variables with non-zero objective coefficient;
6115  * we only want to do the update, if the variable is added to the problem;
6116  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6117  */
6118  if( SCIPvarIsActive(var) )
6119  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6120 
6121  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6122  break;
6123 
6124  case SCIP_VARSTATUS_FIXED:
6125  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6126  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6127  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6128  break;
6129 
6131  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6132  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6133  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6134  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6135  lp, eventqueue, var->data.aggregate.scalar * addobj) );
6136  break;
6137 
6139  assert(!var->donotmultaggr);
6140  /* 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 */
6141  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6142  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6143  for( i = 0; i < var->data.multaggr.nvars; ++i )
6144  {
6145  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6146  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6147  }
6148  break;
6149 
6151  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6152  assert(var->negatedvar != NULL);
6154  assert(var->negatedvar->negatedvar == var);
6155  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6156  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6157  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6158  eventqueue, -addobj) );
6159  break;
6160 
6161  default:
6162  SCIPerrorMessage("unknown variable status\n");
6163  return SCIP_INVALIDDATA;
6164  }
6165  }
6166 
6167  return SCIP_OKAY;
6168 }
6169 
6170 /** changes objective value of variable in current dive */
6172  SCIP_VAR* var, /**< problem variable to change */
6173  SCIP_SET* set, /**< global SCIP settings */
6174  SCIP_LP* lp, /**< current LP data */
6175  SCIP_Real newobj /**< new objective value for variable */
6176  )
6177 {
6178  assert(var != NULL);
6179  assert(set != NULL);
6180  assert(var->scip == set->scip);
6181  assert(lp != NULL);
6182 
6183  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6184 
6185  if( SCIPsetIsZero(set, newobj) )
6186  newobj = 0.0;
6187 
6188  /* change objective value of attached variables */
6189  switch( SCIPvarGetStatus(var) )
6190  {
6192  assert(var->data.original.transvar != NULL);
6193  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6194  break;
6195 
6196  case SCIP_VARSTATUS_COLUMN:
6197  assert(var->data.col != NULL);
6198  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6199  break;
6200 
6201  case SCIP_VARSTATUS_LOOSE:
6202  case SCIP_VARSTATUS_FIXED:
6203  /* nothing to do here: only the constant shift in objective function would change */
6204  break;
6205 
6206  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6207  assert(var->data.aggregate.var != NULL);
6208  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6209  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6210  /* the constant can be ignored, because it would only affect the objective shift */
6211  break;
6212 
6214  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6215  return SCIP_INVALIDDATA;
6216 
6217  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6218  assert(var->negatedvar != NULL);
6220  assert(var->negatedvar->negatedvar == var);
6221  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6222  /* the offset can be ignored, because it would only affect the objective shift */
6223  break;
6224 
6225  default:
6226  SCIPerrorMessage("unknown variable status\n");
6227  return SCIP_INVALIDDATA;
6228  }
6229 
6230  return SCIP_OKAY;
6231 }
6232 
6233 /** adjust lower bound to integral value, if variable is integral */
6234 void SCIPvarAdjustLb(
6235  SCIP_VAR* var, /**< problem variable */
6236  SCIP_SET* set, /**< global SCIP settings */
6237  SCIP_Real* lb /**< pointer to lower bound to adjust */
6238  )
6239 {
6240  assert(var != NULL);
6241  assert(set != NULL);
6242  assert(var->scip == set->scip);
6243  assert(lb != NULL);
6244 
6245  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6246 
6247  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6248 }
6249 
6250 /** adjust upper bound to integral value, if variable is integral */
6251 void SCIPvarAdjustUb(
6252  SCIP_VAR* var, /**< problem variable */
6253  SCIP_SET* set, /**< global SCIP settings */
6254  SCIP_Real* ub /**< pointer to upper bound to adjust */
6255  )
6256 {
6257  assert(var != NULL);
6258  assert(set != NULL);
6259  assert(var->scip == set->scip);
6260  assert(ub != NULL);
6261 
6262  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6263 
6264  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6265 }
6266 
6267 /** adjust lower or upper bound to integral value, if variable is integral */
6268 void SCIPvarAdjustBd(
6269  SCIP_VAR* var, /**< problem variable */
6270  SCIP_SET* set, /**< global SCIP settings */
6271  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6272  SCIP_Real* bd /**< pointer to bound to adjust */
6273  )
6274 {
6275  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6276 
6277  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6278  SCIPvarAdjustLb(var, set, bd);
6279  else
6280  SCIPvarAdjustUb(var, set, bd);
6281 }
6282 
6283 /** changes lower bound of original variable in original problem */
6285  SCIP_VAR* var, /**< problem variable to change */
6286  SCIP_SET* set, /**< global SCIP settings */
6287  SCIP_Real newbound /**< new bound for variable */
6288  )
6289 {
6290  int i;
6291 
6292  assert(var != NULL);
6293  assert(!SCIPvarIsTransformed(var));
6295  assert(set != NULL);
6296  assert(var->scip == set->scip);
6297  assert(set->stage == SCIP_STAGE_PROBLEM);
6298 
6299  /* check that the bound is feasible */
6300  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6301  /* adjust bound to integral value if variable is of integral type */
6302  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6303 
6304  if( SCIPsetIsZero(set, newbound) )
6305  newbound = 0.0;
6306 
6307  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6309  {
6310  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6311  var->name, var->data.original.origdom.lb, newbound);
6312 
6313  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6314  return SCIP_OKAY;
6315 
6316  /* change the bound */
6317  var->data.original.origdom.lb = newbound;
6318  }
6319  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6320  {
6321  assert( var->negatedvar != NULL );
6322  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6323  }
6324 
6325  /* process parent variables */
6326  for( i = 0; i < var->nparentvars; ++i )
6327  {
6328  SCIP_VAR* parentvar;
6329 
6330  parentvar = var->parentvars[i];
6331  assert(parentvar != NULL);
6332  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6333  assert(parentvar->negatedvar == var);
6334  assert(var->negatedvar == parentvar);
6335 
6336  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6337  }
6338 
6339  return SCIP_OKAY;
6340 }
6341 
6342 /** changes upper bound of original variable in original problem */
6344  SCIP_VAR* var, /**< problem variable to change */
6345  SCIP_SET* set, /**< global SCIP settings */
6346  SCIP_Real newbound /**< new bound for variable */
6347  )
6348 {
6349  int i;
6350 
6351  assert(var != NULL);
6352  assert(!SCIPvarIsTransformed(var));
6354  assert(set != NULL);
6355  assert(var->scip == set->scip);
6356  assert(set->stage == SCIP_STAGE_PROBLEM);
6357 
6358  /* check that the bound is feasible */
6359  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6360  /* adjust bound to integral value if variable is of integral type */
6361  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6362 
6363  if( SCIPsetIsZero(set, newbound) )
6364  newbound = 0.0;
6365 
6366  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6368  {
6369  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6370  var->name, var->data.original.origdom.ub, newbound);
6371 
6372  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6373  return SCIP_OKAY;
6374 
6375  /* change the bound */
6376  var->data.original.origdom.ub = newbound;
6377  }
6378  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6379  {
6380  assert( var->negatedvar != NULL );
6381  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6382  }
6383 
6384  /* process parent variables */
6385  for( i = 0; i < var->nparentvars; ++i )
6386  {
6387  SCIP_VAR* parentvar;
6388 
6389  parentvar = var->parentvars[i];
6390  assert(parentvar != NULL);
6391  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6392  assert(parentvar->negatedvar == var);
6393  assert(var->negatedvar == parentvar);
6394 
6395  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6396  }
6397 
6398  return SCIP_OKAY;
6399 }
6400 
6401 /** appends GLBCHANGED event to the event queue */
6402 static
6404  SCIP_VAR* var, /**< problem variable to change */
6405  BMS_BLKMEM* blkmem, /**< block memory */
6406  SCIP_SET* set, /**< global SCIP settings */
6407  SCIP_LP* lp, /**< current LP data */
6408  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6409  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6410  SCIP_Real oldbound, /**< old lower bound for variable */
6411  SCIP_Real newbound /**< new lower bound for variable */
6412  )
6413 {
6414  assert(var != NULL);
6415  assert(var->eventfilter != NULL);
6416  assert(SCIPvarIsTransformed(var));
6417  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6418  assert(set != NULL);
6419  assert(var->scip == set->scip);
6420 
6421  /* check, if the variable is being tracked for bound changes
6422  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6423  */
6424  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6427  {
6428  SCIP_EVENT* event;
6429 
6430  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6431 
6432  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6433  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6434  }
6435 
6436  return SCIP_OKAY;
6437 }
6438 
6439 /** appends GUBCHANGED event to the event queue */
6440 static
6442  SCIP_VAR* var, /**< problem variable to change */
6443  BMS_BLKMEM* blkmem, /**< block memory */
6444  SCIP_SET* set, /**< global SCIP settings */
6445  SCIP_LP* lp, /**< current LP data */
6446  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6447  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6448  SCIP_Real oldbound, /**< old lower bound for variable */
6449  SCIP_Real newbound /**< new lower bound for variable */
6450  )
6451 {
6452  assert(var != NULL);
6453  assert(var->eventfilter != NULL);
6454  assert(SCIPvarIsTransformed(var));
6455  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6456  assert(set != NULL);
6457  assert(var->scip == set->scip);
6458 
6459  /* check, if the variable is being tracked for bound changes
6460  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6461  */
6462  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6465  {
6466  SCIP_EVENT* event;
6467 
6468  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6469 
6470  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6471  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6472  }
6473 
6474  return SCIP_OKAY;
6475 }
6476 
6477 /** appends GHOLEADDED event to the event queue */
6478 static
6480  SCIP_VAR* var, /**< problem variable to change */
6481  BMS_BLKMEM* blkmem, /**< block memory */
6482  SCIP_SET* set, /**< global SCIP settings */
6483  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6484  SCIP_Real left, /**< left bound of open interval in new hole */
6485  SCIP_Real right /**< right bound of open interval in new hole */
6486  )
6487 {
6488  assert(var != NULL);
6489  assert(var->eventfilter != NULL);
6490  assert(SCIPvarIsTransformed(var));
6491  assert(set != NULL);
6492  assert(var->scip == set->scip);
6493  assert(SCIPsetIsLT(set, left, right));
6494 
6495  /* check, if the variable is being tracked for bound changes */
6496  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6497  {
6498  SCIP_EVENT* event;
6499 
6500  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6501 
6502  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6503  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6504  }
6505 
6506  return SCIP_OKAY;
6507 }
6508 
6509 /** increases root bound change statistics after a global bound change */
6510 static
6511 void varIncRootboundchgs(
6512  SCIP_VAR* var, /**< problem variable to change */
6513  SCIP_SET* set, /**< global SCIP settings */
6514  SCIP_STAT* stat /**< problem statistics */
6515  )
6516 {
6517  assert(var != NULL);
6518  assert(set != NULL);
6519  assert(var->scip == set->scip);
6520  assert(stat != NULL);
6521 
6522  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6523  {
6524  stat->nrootboundchgs++;
6525  stat->nrootboundchgsrun++;
6526  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6527  {
6528  stat->nrootintfixings++;
6529  stat->nrootintfixingsrun++;
6530  }
6531  }
6532 }
6533 
6534 /* forward declaration, because both methods call each other recursively */
6535 
6536 /* performs the current change in upper 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 /** performs the current change in lower bound, changes all parents accordingly */
6551 static
6553  SCIP_VAR* var, /**< problem variable to change */
6554  BMS_BLKMEM* blkmem, /**< block memory */
6555  SCIP_SET* set, /**< global SCIP settings */
6556  SCIP_STAT* stat, /**< problem statistics */
6557  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6558  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6559  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6560  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6561  SCIP_Real newbound /**< new bound for variable */
6562  )
6563 {
6564  SCIP_VAR* parentvar;
6565  SCIP_Real oldbound;
6566  int i;
6567 
6568  assert(var != NULL);
6569  /* local domains can violate global bounds but not more than feasibility epsilon */
6570  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6571  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6572  assert(blkmem != NULL);
6573  assert(set != NULL);
6574  assert(var->scip == set->scip);
6575  assert(stat != NULL);
6576 
6577  /* adjust bound to integral value if variable is of integral type */
6578  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6579 
6580  /* check that the bound is feasible */
6581  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6582  {
6583  /* due to numerics we only want to be feasible in feasibility tolerance */
6584  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6585  newbound = var->glbdom.ub;
6586  }
6587  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6588 
6589  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6590 
6591  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6592 
6593  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6594  return SCIP_OKAY;
6595 
6596  /* check bound on debugging solution */
6597  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6598 
6599  /* change the bound */
6600  oldbound = var->glbdom.lb;
6601  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6602  var->glbdom.lb = newbound;
6603  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6604  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6605 
6606  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6607  {
6608  /* merges overlapping holes into single holes, moves bounds respectively */
6609  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6610  }
6611 
6612  /* update the root bound changes counters */
6613  varIncRootboundchgs(var, set, stat);
6614 
6615  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6616  * redundant bound changes to be branching decisions
6617  */
6618  for( i = 0; i < var->nlbchginfos; ++i )
6619  {
6620  assert(var->lbchginfos[i].var == var);
6621 
6622  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6623  {
6624  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6625  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6626  var->lbchginfos[i].oldbound = var->glbdom.lb;
6627  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6628  {
6629  /* this bound change is redundant due to the new global bound */
6630  var->lbchginfos[i].newbound = var->glbdom.lb;
6631  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6632  var->lbchginfos[i].redundant = TRUE;
6633  }
6634  else
6635  break; /* from now on, the remaining local bound changes are not redundant */
6636  }
6637  else
6638  break; /* from now on, the remaining local bound changes are not redundant */
6639  }
6640 
6641  /* remove redundant implications and variable bounds */
6643  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6644  {
6645  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6646  }
6647 
6648  /* issue bound change event */
6649  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6650  if( var->eventfilter != NULL )
6651  {
6652  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6653  }
6654 
6655  /* process parent variables */
6656  for( i = 0; i < var->nparentvars; ++i )
6657  {
6658  parentvar = var->parentvars[i];
6659  assert(parentvar != NULL);
6660 
6661  switch( SCIPvarGetStatus(parentvar) )
6662  {
6664  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6665  break;
6666 
6667  case SCIP_VARSTATUS_COLUMN:
6668  case SCIP_VARSTATUS_LOOSE:
6669  case SCIP_VARSTATUS_FIXED:
6671  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6672  return SCIP_INVALIDDATA;
6673 
6674  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6675  assert(parentvar->data.aggregate.var == var);
6676  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6677  {
6678  SCIP_Real parentnewbound;
6679 
6680  /* a > 0 -> change lower bound of y */
6681  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6682  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6683  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6684 
6685  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6686  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6687  else
6688  parentnewbound = newbound;
6689  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6690  }
6691  else
6692  {
6693  SCIP_Real parentnewbound;
6694 
6695  /* a < 0 -> change upper bound of y */
6696  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6697  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6698  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6699  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6700 
6701  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6702  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6703  else
6704  parentnewbound = -newbound;
6705  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6706  }
6707  break;
6708 
6709  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6710  assert(parentvar->negatedvar != NULL);
6711  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6712  assert(parentvar->negatedvar->negatedvar == parentvar);
6713  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6714  parentvar->data.negate.constant - newbound) );
6715  break;
6716 
6717  default:
6718  SCIPerrorMessage("unknown variable status\n");
6719  return SCIP_INVALIDDATA;
6720  }
6721  }
6722 
6723  return SCIP_OKAY;
6724 }
6725 
6726 /** performs the current change in upper bound, changes all parents accordingly */
6727 static
6729  SCIP_VAR* var, /**< problem variable to change */
6730  BMS_BLKMEM* blkmem, /**< block memory */
6731  SCIP_SET* set, /**< global SCIP settings */
6732  SCIP_STAT* stat, /**< problem statistics */
6733  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6734  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6735  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6736  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6737  SCIP_Real newbound /**< new bound for variable */
6738  )
6739 {
6740  SCIP_VAR* parentvar;
6741  SCIP_Real oldbound;
6742  int i;
6743 
6744  assert(var != NULL);
6745  /* local domains can violate global bounds but not more than feasibility epsilon */
6746  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6747  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6748  assert(blkmem != NULL);
6749  assert(set != NULL);
6750  assert(var->scip == set->scip);
6751  assert(stat != NULL);
6752 
6753  /* adjust bound to integral value if variable is of integral type */
6754  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6755 
6756  /* check that the bound is feasible */
6757  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6758  {
6759  /* due to numerics we only want to be feasible in feasibility tolerance */
6760  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6761  newbound = var->glbdom.lb;
6762  }
6763  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6764 
6765  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6766 
6767  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6768 
6769  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6770  return SCIP_OKAY;
6771 
6772  /* check bound on debugging solution */
6773  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6774 
6775  /* change the bound */
6776  oldbound = var->glbdom.ub;
6777  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6778  var->glbdom.ub = newbound;
6779  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6780  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6781 
6782  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6783  {
6784  /* merges overlapping holes into single holes, moves bounds respectively */
6785  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6786  }
6787 
6788  /* update the root bound changes counters */
6789  varIncRootboundchgs(var, set, stat);
6790 
6791  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6792  * redundant bound changes to be branching decisions
6793  */
6794  for( i = 0; i < var->nubchginfos; ++i )
6795  {
6796  assert(var->ubchginfos[i].var == var);
6797  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6798  {
6799  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6800  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6801  var->ubchginfos[i].oldbound = var->glbdom.ub;
6802  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6803  {
6804  /* this bound change is redundant due to the new global bound */
6805  var->ubchginfos[i].newbound = var->glbdom.ub;
6806  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6807  var->ubchginfos[i].redundant = TRUE;
6808  }
6809  else
6810  break; /* from now on, the remaining local bound changes are not redundant */
6811  }
6812  else
6813  break; /* from now on, the remaining local bound changes are not redundant */
6814  }
6815 
6816  /* remove redundant implications and variable bounds */
6818  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6819  {
6820  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6821  }
6822 
6823  /* issue bound change event */
6824  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6825  if( var->eventfilter != NULL )
6826  {
6827  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6828  }
6829 
6830  /* process parent variables */
6831  for( i = 0; i < var->nparentvars; ++i )
6832  {
6833  parentvar = var->parentvars[i];
6834  assert(parentvar != NULL);
6835 
6836  switch( SCIPvarGetStatus(parentvar) )
6837  {
6839  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6840  break;
6841 
6842  case SCIP_VARSTATUS_COLUMN:
6843  case SCIP_VARSTATUS_LOOSE:
6844  case SCIP_VARSTATUS_FIXED:
6846  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6847  return SCIP_INVALIDDATA;
6848 
6849  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6850  assert(parentvar->data.aggregate.var == var);
6851  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6852  {
6853  SCIP_Real parentnewbound;
6854 
6855  /* a > 0 -> change upper bound of y */
6856  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
6857  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6858  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6859  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6860  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6861  else
6862  parentnewbound = newbound;
6863  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6864  }
6865  else
6866  {
6867  SCIP_Real parentnewbound;
6868 
6869  /* a < 0 -> change lower bound of y */
6870  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6871  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
6872  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6873  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6874  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6875  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6876  else
6877  parentnewbound = -newbound;
6878  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6879  }
6880  break;
6881 
6882  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6883  assert(parentvar->negatedvar != NULL);
6884  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6885  assert(parentvar->negatedvar->negatedvar == parentvar);
6886  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6887  parentvar->data.negate.constant - newbound) );
6888  break;
6889 
6890  default:
6891  SCIPerrorMessage("unknown variable status\n");
6892  return SCIP_INVALIDDATA;
6893  }
6894  }
6895 
6896  return SCIP_OKAY;
6897 }
6898 
6899 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6900  * updates local lower bound if the global bound is tighter
6901  */
6903  SCIP_VAR* var, /**< problem variable to change */
6904  BMS_BLKMEM* blkmem, /**< block memory */
6905  SCIP_SET* set, /**< global SCIP settings */
6906  SCIP_STAT* stat, /**< problem statistics */
6907  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6908  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6909  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6910  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6911  SCIP_Real newbound /**< new bound for variable */
6912  )
6913 {
6914  assert(var != NULL);
6915  assert(blkmem != NULL);
6916  assert(set != NULL);
6917  assert(var->scip == set->scip);
6918 
6919  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6920  * of the domain within feastol
6921  */
6922  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6923 
6924  /* adjust bound to integral value if variable is of integral type */
6925  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6926 
6927  /* check that the adjusted bound is feasible
6928  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6929  * here because we reset bounds to their original value!
6930  */
6931  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6932 
6933  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6934  {
6935  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6936  newbound = MIN(newbound, var->glbdom.ub);
6937  }
6938  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6939 
6940  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6941  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6942  */
6943  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6944 
6945  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6946 
6947  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6948  return SCIP_OKAY;
6949 
6950  /* change bounds of attached variables */
6951  switch( SCIPvarGetStatus(var) )
6952  {
6954  if( var->data.original.transvar != NULL )
6955  {
6956  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6957  cliquetable, newbound) );
6958  }
6959  else
6960  {
6961  assert(set->stage == SCIP_STAGE_PROBLEM);
6962  if( newbound > SCIPvarGetLbLocal(var) )
6963  {
6964  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6965  }
6966  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6967  }
6968  break;
6969 
6970  case SCIP_VARSTATUS_COLUMN:
6971  case SCIP_VARSTATUS_LOOSE:
6972  if( newbound > SCIPvarGetLbLocal(var) )
6973  {
6974  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6975  }
6976  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6977  break;
6978 
6979  case SCIP_VARSTATUS_FIXED:
6980  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6981  return SCIP_INVALIDDATA;
6982 
6983  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6984  assert(var->data.aggregate.var != NULL);
6985  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6986  {
6987  SCIP_Real childnewbound;
6988 
6989  /* a > 0 -> change lower bound of y */
6990  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6991  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6993  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6994  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6995  else
6996  childnewbound = newbound;
6997  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6998  childnewbound) );
6999  }
7000  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7001  {
7002  SCIP_Real childnewbound;
7003 
7004  /* a < 0 -> change upper bound of y */
7005  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7006  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7008  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7009  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7010  else
7011  childnewbound = -newbound;
7012  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7013  childnewbound) );
7014  }
7015  else
7016  {
7017  SCIPerrorMessage("scalar is zero in aggregation\n");
7018  return SCIP_INVALIDDATA;
7019  }
7020  break;
7021 
7023  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7024  return SCIP_INVALIDDATA;
7025 
7026  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7027  assert(var->negatedvar != NULL);
7029  assert(var->negatedvar->negatedvar == var);
7030  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7031  var->data.negate.constant - newbound) );
7032  break;
7033 
7034  default:
7035  SCIPerrorMessage("unknown variable status\n");
7036  return SCIP_INVALIDDATA;
7037  }
7038 
7039  return SCIP_OKAY;
7040 }
7041 
7042 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7043  * updates local upper bound if the global bound is tighter
7044  */
7046  SCIP_VAR* var, /**< problem variable to change */
7047  BMS_BLKMEM* blkmem, /**< block memory */
7048  SCIP_SET* set, /**< global SCIP settings */
7049  SCIP_STAT* stat, /**< problem statistics */
7050  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7051  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7052  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7053  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7054  SCIP_Real newbound /**< new bound for variable */
7055  )
7056 {
7057  assert(var != NULL);
7058  assert(blkmem != NULL);
7059  assert(set != NULL);
7060  assert(var->scip == set->scip);
7061 
7062  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7063  * of the domain within feastol
7064  */
7065  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7066 
7067  /* adjust bound to integral value if variable is of integral type */
7068  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7069 
7070  /* check that the adjusted bound is feasible
7071  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7072  * here because we reset bounds to their original value!
7073  */
7074  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7075 
7076  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7077  {
7078  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7079  newbound = MAX(newbound, var->glbdom.lb);
7080  }
7081  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7082 
7083  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7084  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7085  */
7086  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7087 
7088  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7089 
7090  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
7091  return SCIP_OKAY;
7092 
7093  /* change bounds of attached variables */
7094  switch( SCIPvarGetStatus(var) )
7095  {
7097  if( var->data.original.transvar != NULL )
7098  {
7099  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7100  newbound) );
7101  }
7102  else
7103  {
7104  assert(set->stage == SCIP_STAGE_PROBLEM);
7105  if( newbound < SCIPvarGetUbLocal(var) )
7106  {
7107  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7108  }
7109  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7110  }
7111  break;
7112 
7113  case SCIP_VARSTATUS_COLUMN:
7114  case SCIP_VARSTATUS_LOOSE:
7115  if( newbound < SCIPvarGetUbLocal(var) )
7116  {
7117  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7118  }
7119  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7120  break;
7121 
7122  case SCIP_VARSTATUS_FIXED:
7123  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7124  return SCIP_INVALIDDATA;
7125 
7126  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7127  assert(var->data.aggregate.var != NULL);
7128  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7129  {
7130  SCIP_Real childnewbound;
7131 
7132  /* a > 0 -> change lower bound of y */
7133  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7134  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7136  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7137  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7138  else
7139  childnewbound = newbound;
7140  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7141  childnewbound) );
7142  }
7143  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7144  {
7145  SCIP_Real childnewbound;
7146 
7147  /* a < 0 -> change upper bound of y */
7148  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7149  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7151  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7152  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7153  else
7154  childnewbound = -newbound;
7155  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7156  childnewbound) );
7157  }
7158  else
7159  {
7160  SCIPerrorMessage("scalar is zero in aggregation\n");
7161  return SCIP_INVALIDDATA;
7162  }
7163  break;
7164 
7166  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7167  return SCIP_INVALIDDATA;
7168 
7169  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7170  assert(var->negatedvar != NULL);
7172  assert(var->negatedvar->negatedvar == var);
7173  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7174  var->data.negate.constant - newbound) );
7175  break;
7176 
7177  default:
7178  SCIPerrorMessage("unknown variable status\n");
7179  return SCIP_INVALIDDATA;
7180  }
7181 
7182  return SCIP_OKAY;
7183 }
7184 
7185 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7187  SCIP_VAR* var, /**< problem variable */
7188  SCIP_SET* set, /**< global SCIP settings */
7189  SCIP_Real lazylb /**< the lazy lower bound to be set */
7190  )
7191 {
7192  assert(var != NULL);
7193  assert(var->probindex != -1);
7194  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7195  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7196  assert(set != NULL);
7197  assert(var->scip == set->scip);
7198 
7199  /* variable should not be in the LP */
7201  return SCIP_INVALIDCALL;
7202 
7203  var->lazylb = lazylb;
7204 
7205  return SCIP_OKAY;
7206 }
7207 
7208 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7210  SCIP_VAR* var, /**< problem variable */
7211  SCIP_SET* set, /**< global SCIP settings */
7212  SCIP_Real lazyub /**< the lazy lower bound to be set */
7213  )
7214 {
7215  assert(var != NULL);
7216  assert(var->probindex != -1);
7217  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7218  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7219  assert(set != NULL);
7220  assert(var->scip == set->scip);
7221 
7222  /* variable should not be in the LP */
7224  return SCIP_INVALIDCALL;
7225 
7226  var->lazyub = lazyub;
7227 
7228  return SCIP_OKAY;
7229 }
7230 
7231 
7232 /** changes global bound of variable; if possible, adjusts bound to integral value;
7233  * updates local bound if the global bound is tighter
7234  */
7236  SCIP_VAR* var, /**< problem variable to change */
7237  BMS_BLKMEM* blkmem, /**< block memory */
7238  SCIP_SET* set, /**< global SCIP settings */
7239  SCIP_STAT* stat, /**< problem statistics */
7240  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7241  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7242  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7243  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7244  SCIP_Real newbound, /**< new bound for variable */
7245  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7246  )
7247 {
7248  /* apply bound change to the LP data */
7249  switch( boundtype )
7250  {
7251  case SCIP_BOUNDTYPE_LOWER:
7252  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7253  case SCIP_BOUNDTYPE_UPPER:
7254  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7255  default:
7256  SCIPerrorMessage("unknown bound type\n");
7257  return SCIP_INVALIDDATA;
7258  }
7259 }
7260 
7261 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7262 static
7264  SCIP_VAR* var, /**< problem variable to change */
7265  BMS_BLKMEM* blkmem, /**< block memory */
7266  SCIP_SET* set, /**< global SCIP settings */
7267  SCIP_LP* lp, /**< current LP data */
7268  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7269  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7270  SCIP_Real oldbound, /**< old lower bound for variable */
7271  SCIP_Real newbound /**< new lower bound for variable */
7272  )
7273 {
7274  assert(var != NULL);
7275  assert(var->eventfilter != NULL);
7276  assert(SCIPvarIsTransformed(var));
7277  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb); /*lint !e777*/
7278  assert(set != NULL);
7279  assert(var->scip == set->scip);
7280 
7281  /* check, if the variable is being tracked for bound changes
7282  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7283  */
7284  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7287  {
7288  SCIP_EVENT* event;
7289 
7290  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7291 
7292  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7293  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7294  }
7295 
7296  return SCIP_OKAY;
7297 }
7298 
7299 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7300 static
7302  SCIP_VAR* var, /**< problem variable to change */
7303  BMS_BLKMEM* blkmem, /**< block memory */
7304  SCIP_SET* set, /**< global SCIP settings */
7305  SCIP_LP* lp, /**< current LP data */
7306  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7307  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7308  SCIP_Real oldbound, /**< old upper bound for variable */
7309  SCIP_Real newbound /**< new upper bound for variable */
7310  )
7311 {
7312  assert(var != NULL);
7313  assert(var->eventfilter != NULL);
7314  assert(SCIPvarIsTransformed(var));
7315  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub); /*lint !e777*/
7316  assert(set != NULL);
7317  assert(var->scip == set->scip);
7318 
7319  /* check, if the variable is being tracked for bound changes
7320  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7321  */
7322  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7325  {
7326  SCIP_EVENT* event;
7327 
7328  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7329 
7330  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7331  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7332  }
7333 
7334  return SCIP_OKAY;
7335 }
7336 
7337 /* forward declaration, because both methods call each other recursively */
7338 
7339 /* performs the current change in upper bound, changes all parents accordingly */
7340 static
7342  SCIP_VAR* var, /**< problem variable to change */
7343  BMS_BLKMEM* blkmem, /**< block memory */
7344  SCIP_SET* set, /**< global SCIP settings */
7345  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7346  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7347  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7348  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7349  SCIP_Real newbound /**< new bound for variable */
7350  );
7351 
7352 /** performs the current change in lower bound, changes all parents accordingly */
7353 static
7355  SCIP_VAR* var, /**< problem variable to change */
7356  BMS_BLKMEM* blkmem, /**< block memory */
7357  SCIP_SET* set, /**< global SCIP settings */
7358  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7359  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7360  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7361  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7362  SCIP_Real newbound /**< new bound for variable */
7363  )
7364 {
7365  SCIP_VAR* parentvar;
7366  SCIP_Real oldbound;
7367  int i;
7368 
7369  assert(var != NULL);
7370  assert(set != NULL);
7371  assert(var->scip == set->scip);
7372  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7373  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7374  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7375  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7377 
7378  /* check that the bound is feasible */
7379  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7380  /* adjust bound to integral value if variable is of integral type */
7381  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7382 
7383  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7384  {
7385  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7386  newbound = MIN(newbound, var->locdom.ub);
7387 
7388  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7389  newbound = MAX(newbound, var->glbdom.lb);
7390  }
7391  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7392 
7393  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7394 
7395  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7396  newbound = var->glbdom.lb;
7397  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7398  return SCIP_OKAY;
7399 
7400  /* change the bound */
7401  oldbound = var->locdom.lb;
7402  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7403  var->locdom.lb = newbound;
7404 
7405  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7406  * once update the statistic
7407  */
7408  if( stat != NULL )
7409  SCIPstatIncrement(stat, set, domchgcount);
7410 
7411  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7412  {
7413  /* merges overlapping holes into single holes, moves bounds respectively */
7414  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7415  }
7416 
7417  /* issue bound change event */
7418  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7419  if( var->eventfilter != NULL )
7420  {
7421  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7422  }
7423 
7424  /* process parent variables */
7425  for( i = 0; i < var->nparentvars; ++i )
7426  {
7427  parentvar = var->parentvars[i];
7428  assert(parentvar != NULL);
7429 
7430  switch( SCIPvarGetStatus(parentvar) )
7431  {
7433  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7434  break;
7435 
7436  case SCIP_VARSTATUS_COLUMN:
7437  case SCIP_VARSTATUS_LOOSE:
7438  case SCIP_VARSTATUS_FIXED:
7440  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7441  return SCIP_INVALIDDATA;
7442 
7443  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7444  assert(parentvar->data.aggregate.var == var);
7445  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7446  {
7447  SCIP_Real parentnewbound;
7448 
7449  /* a > 0 -> change lower bound of y */
7450  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7451  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7452  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7453 
7454  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7455  {
7456  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7457  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7458  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7459  * as a result, the parent's lower bound is set to it's upper bound, and not above
7460  */
7461  if( parentnewbound > parentvar->glbdom.ub )
7462  {
7463  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7464  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7465  parentnewbound = parentvar->glbdom.ub;
7466  }
7467  }
7468  else
7469  parentnewbound = newbound;
7470  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7471  }
7472  else
7473  {
7474  SCIP_Real parentnewbound;
7475 
7476  /* a < 0 -> change upper bound of y */
7477  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7478  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7479  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7480  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7481 
7482  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7483  {
7484  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7485  /* 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
7486  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7487  * as a result, the parent's upper bound is set to it's lower bound, and not below
7488  */
7489  if( parentnewbound < parentvar->glbdom.lb )
7490  {
7491  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7492  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7493  parentnewbound = parentvar->glbdom.lb;
7494  }
7495  }
7496  else
7497  parentnewbound = -newbound;
7498  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7499  }
7500  break;
7501 
7502  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7503  assert(parentvar->negatedvar != NULL);
7504  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7505  assert(parentvar->negatedvar->negatedvar == parentvar);
7506  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7507  parentvar->data.negate.constant - newbound) );
7508  break;
7509 
7510  default:
7511  SCIPerrorMessage("unknown variable status\n");
7512  return SCIP_INVALIDDATA;
7513  }
7514  }
7515 
7516  return SCIP_OKAY;
7517 }
7518 
7519 /** performs the current change in upper bound, changes all parents accordingly */
7520 static
7522  SCIP_VAR* var, /**< problem variable to change */
7523  BMS_BLKMEM* blkmem, /**< block memory */
7524  SCIP_SET* set, /**< global SCIP settings */
7525  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7526  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7527  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7528  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7529  SCIP_Real newbound /**< new bound for variable */
7530  )
7531 {
7532  SCIP_VAR* parentvar;
7533  SCIP_Real oldbound;
7534  int i;
7535 
7536  assert(var != NULL);
7537  assert(set != NULL);
7538  assert(var->scip == set->scip);
7539  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7540  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7541  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7542  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7544 
7545  /* check that the bound is feasible */
7546  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7547  /* adjust bound to integral value if variable is of integral type */
7548  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7549 
7550  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7551  {
7552  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7553  newbound = MAX(newbound, var->locdom.lb);
7554 
7555  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7556  newbound = MIN(newbound, var->glbdom.ub);
7557  }
7558  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7559 
7560  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7561 
7562  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7563  newbound = var->glbdom.ub;
7564  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7565  return SCIP_OKAY;
7566 
7567  /* change the bound */
7568  oldbound = var->locdom.ub;
7569  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7570  var->locdom.ub = newbound;
7571 
7572  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7573  * once update the statistic
7574  */
7575  if( stat != NULL )
7576  SCIPstatIncrement(stat, set, domchgcount);
7577 
7578  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7579  {
7580  /* merges overlapping holes into single holes, moves bounds respectively */
7581  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7582  }
7583 
7584  /* issue bound change event */
7585  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7586  if( var->eventfilter != NULL )
7587  {
7588  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7589  }
7590 
7591  /* process parent variables */
7592  for( i = 0; i < var->nparentvars; ++i )
7593  {
7594  parentvar = var->parentvars[i];
7595  assert(parentvar != NULL);
7596 
7597  switch( SCIPvarGetStatus(parentvar) )
7598  {
7600  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7601  break;
7602 
7603  case SCIP_VARSTATUS_COLUMN:
7604  case SCIP_VARSTATUS_LOOSE:
7605  case SCIP_VARSTATUS_FIXED:
7607  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7608  return SCIP_INVALIDDATA;
7609 
7610  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7611  assert(parentvar->data.aggregate.var == var);
7612  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7613  {
7614  SCIP_Real parentnewbound;
7615 
7616  /* a > 0 -> change upper bound of x */
7617  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7618  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7619  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7620  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7621  {
7622  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7623  /* 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
7624  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7625  * as a result, the parent's upper bound is set to it's lower bound, and not below
7626  */
7627  if( parentnewbound < parentvar->glbdom.lb )
7628  {
7629  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7630  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7631  parentnewbound = parentvar->glbdom.lb;
7632  }
7633  }
7634  else
7635  parentnewbound = newbound;
7636  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7637  }
7638  else
7639  {
7640  SCIP_Real parentnewbound;
7641 
7642  /* a < 0 -> change lower bound of x */
7643  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7644  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7645  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7646  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7647  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7648  {
7649  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7650  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7651  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7652  * as a result, the parent's lower bound is set to it's upper bound, and not above
7653  */
7654  if( parentnewbound > parentvar->glbdom.ub )
7655  {
7656  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7657  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7658  parentnewbound = parentvar->glbdom.ub;
7659  }
7660  }
7661  else
7662  parentnewbound = -newbound;
7663  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7664  }
7665  break;
7666 
7667  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7668  assert(parentvar->negatedvar != NULL);
7669  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7670  assert(parentvar->negatedvar->negatedvar == parentvar);
7671  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7672  parentvar->data.negate.constant - newbound) );
7673  break;
7674 
7675  default:
7676  SCIPerrorMessage("unknown variable status\n");
7677  return SCIP_INVALIDDATA;
7678  }
7679  }
7680 
7681  return SCIP_OKAY;
7682 }
7683 
7684 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7685  * information in variable
7686  */
7688  SCIP_VAR* var, /**< problem variable to change */
7689  BMS_BLKMEM* blkmem, /**< block memory */
7690  SCIP_SET* set, /**< global SCIP settings */
7691  SCIP_STAT* stat, /**< problem statistics */
7692  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7693  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7694  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7695  SCIP_Real newbound /**< new bound for variable */
7696  )
7697 {
7698  assert(var != NULL);
7699  assert(blkmem != NULL);
7700  assert(set != NULL);
7701  assert(var->scip == set->scip);
7702 
7703  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7704  * of the domain within feastol
7705  */
7706  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7707 
7708  /* adjust bound to integral value if variable is of integral type */
7709  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7710 
7711  /* check that the adjusted bound is feasible */
7712  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7713 
7714  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7715  {
7716  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7717  newbound = MIN(newbound, var->locdom.ub);
7718  }
7719  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7720 
7721  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7722 
7723  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) ) /*lint !e777*/
7724  return SCIP_OKAY;
7725 
7726  /* change bounds of attached variables */
7727  switch( SCIPvarGetStatus(var) )
7728  {
7730  if( var->data.original.transvar != NULL )
7731  {
7732  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7733  newbound) );
7734  }
7735  else
7736  {
7737  assert(set->stage == SCIP_STAGE_PROBLEM);
7738  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7739  }
7740  break;
7741 
7742  case SCIP_VARSTATUS_COLUMN:
7743  case SCIP_VARSTATUS_LOOSE:
7744  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7745  break;
7746 
7747  case SCIP_VARSTATUS_FIXED:
7748  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7749  return SCIP_INVALIDDATA;
7750 
7751  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7752  assert(var->data.aggregate.var != NULL);
7753  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7754  {
7755  SCIP_Real childnewbound;
7756 
7757  /* a > 0 -> change lower bound of y */
7758  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7759  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7761  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7762  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7763  else
7764  childnewbound = newbound;
7765  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7766  childnewbound) );
7767  }
7768  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7769  {
7770  SCIP_Real childnewbound;
7771 
7772  /* a < 0 -> change upper bound of y */
7773  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7774  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7776  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7777  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7778  else
7779  childnewbound = -newbound;
7780  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7781  childnewbound) );
7782  }
7783  else
7784  {
7785  SCIPerrorMessage("scalar is zero in aggregation\n");
7786  return SCIP_INVALIDDATA;
7787  }
7788  break;
7789 
7791  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7792  return SCIP_INVALIDDATA;
7793 
7794  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7795  assert(var->negatedvar != NULL);
7797  assert(var->negatedvar->negatedvar == var);
7798  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7799  var->data.negate.constant - newbound) );
7800  break;
7801 
7802  default:
7803  SCIPerrorMessage("unknown variable status\n");
7804  return SCIP_INVALIDDATA;
7805  }
7806 
7807  return SCIP_OKAY;
7808 }
7809 
7810 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7811  * information in variable
7812  */
7814  SCIP_VAR* var, /**< problem variable to change */
7815  BMS_BLKMEM* blkmem, /**< block memory */
7816  SCIP_SET* set, /**< global SCIP settings */
7817  SCIP_STAT* stat, /**< problem statistics */
7818  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7819  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7820  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7821  SCIP_Real newbound /**< new bound for variable */
7822  )
7823 {
7824  assert(var != NULL);
7825  assert(blkmem != NULL);
7826  assert(set != NULL);
7827  assert(var->scip == set->scip);
7828 
7829  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7830  * of the domain within feastol
7831  */
7832  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7833 
7834  /* adjust bound to integral value if variable is of integral type */
7835  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7836 
7837  /* check that the adjusted bound is feasible */
7838  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7839 
7840  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7841  {
7842  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7843  newbound = MAX(newbound, var->locdom.lb);
7844  }
7845  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7846 
7847  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7848 
7849  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) ) /*lint !e777*/
7850  return SCIP_OKAY;
7851 
7852  /* change bounds of attached variables */
7853  switch( SCIPvarGetStatus(var) )
7854  {
7856  if( var->data.original.transvar != NULL )
7857  {
7858  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7859  }
7860  else
7861  {
7862  assert(set->stage == SCIP_STAGE_PROBLEM);
7863  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7864  }
7865  break;
7866 
7867  case SCIP_VARSTATUS_COLUMN:
7868  case SCIP_VARSTATUS_LOOSE:
7869  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7870  break;
7871 
7872  case SCIP_VARSTATUS_FIXED:
7873  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7874  return SCIP_INVALIDDATA;
7875 
7876  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7877  assert(var->data.aggregate.var != NULL);
7878  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7879  {
7880  SCIP_Real childnewbound;
7881 
7882  /* a > 0 -> change upper bound of y */
7883  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7884  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7886  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7887  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7888  else
7889  childnewbound = newbound;
7890  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7891  childnewbound) );
7892  }
7893  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7894  {
7895  SCIP_Real childnewbound;
7896 
7897  /* a < 0 -> change lower bound of y */
7898  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7899  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7901  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7902  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7903  else
7904  childnewbound = -newbound;
7905  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7906  childnewbound) );
7907  }
7908  else
7909  {
7910  SCIPerrorMessage("scalar is zero in aggregation\n");
7911  return SCIP_INVALIDDATA;
7912  }
7913  break;
7914 
7916  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7917  return SCIP_INVALIDDATA;
7918 
7919  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7920  assert(var->negatedvar != NULL);
7922  assert(var->negatedvar->negatedvar == var);
7923  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7924  var->data.negate.constant - newbound) );
7925  break;
7926 
7927  default:
7928  SCIPerrorMessage("unknown variable status\n");
7929  return SCIP_INVALIDDATA;
7930  }
7931 
7932  return SCIP_OKAY;
7933 }
7934 
7935 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7936  * information in variable
7937  */
7939  SCIP_VAR* var, /**< problem variable to change */
7940  BMS_BLKMEM* blkmem, /**< block memory */
7941  SCIP_SET* set, /**< global SCIP settings */
7942  SCIP_STAT* stat, /**< problem statistics */
7943  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7944  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7945  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7946  SCIP_Real newbound, /**< new bound for variable */
7947  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7948  )
7949 {
7950  /* apply bound change to the LP data */
7951  switch( boundtype )
7952  {
7953  case SCIP_BOUNDTYPE_LOWER:
7954  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7955  case SCIP_BOUNDTYPE_UPPER:
7956  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7957  default:
7958  SCIPerrorMessage("unknown bound type\n");
7959  return SCIP_INVALIDDATA;
7960  }
7961 }
7962 
7963 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7965  SCIP_VAR* var, /**< problem variable to change */
7966  SCIP_SET* set, /**< global SCIP settings */
7967  SCIP_LP* lp, /**< current LP data */
7968  SCIP_Real newbound /**< new bound for variable */
7969  )
7970 {
7971  assert(var != NULL);
7972  assert(set != NULL);
7973  assert(var->scip == set->scip);
7974  assert(lp != NULL);
7975  assert(SCIPlpDiving(lp));
7976 
7977  /* adjust bound for integral variables */
7978  SCIPvarAdjustLb(var, set, &newbound);
7979 
7980  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7981 
7982  /* change bounds of attached variables */
7983  switch( SCIPvarGetStatus(var) )
7984  {
7986  assert(var->data.original.transvar != NULL);
7987  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7988  break;
7989 
7990  case SCIP_VARSTATUS_COLUMN:
7991  assert(var->data.col != NULL);
7992  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7993  break;
7994 
7995  case SCIP_VARSTATUS_LOOSE:
7996  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7997  return SCIP_INVALIDDATA;
7998 
7999  case SCIP_VARSTATUS_FIXED:
8000  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8001  return SCIP_INVALIDDATA;
8002 
8003  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8004  assert(var->data.aggregate.var != NULL);
8005  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8006  {
8007  SCIP_Real childnewbound;
8008 
8009  /* a > 0 -> change lower bound of y */
8010  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8011  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8012  else
8013  childnewbound = newbound;
8014  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8015  }
8016  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8017  {
8018  SCIP_Real childnewbound;
8019 
8020  /* a < 0 -> change upper bound of y */
8021  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8022  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8023  else
8024  childnewbound = -newbound;
8025  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8026  }
8027  else
8028  {
8029  SCIPerrorMessage("scalar is zero in aggregation\n");
8030  return SCIP_INVALIDDATA;
8031  }
8032  break;
8033 
8035  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8036  return SCIP_INVALIDDATA;
8037 
8038  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8039  assert(var->negatedvar != NULL);
8041  assert(var->negatedvar->negatedvar == var);
8042  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8043  break;
8044 
8045  default:
8046  SCIPerrorMessage("unknown variable status\n");
8047  return SCIP_INVALIDDATA;
8048  }
8049 
8050  return SCIP_OKAY;
8051 }
8052 
8053 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8055  SCIP_VAR* var, /**< problem variable to change */
8056  SCIP_SET* set, /**< global SCIP settings */
8057  SCIP_LP* lp, /**< current LP data */
8058  SCIP_Real newbound /**< new bound for variable */
8059  )
8060 {
8061  assert(var != NULL);
8062  assert(set != NULL);
8063  assert(var->scip == set->scip);
8064  assert(lp != NULL);
8065  assert(SCIPlpDiving(lp));
8066 
8067  /* adjust bound for integral variables */
8068  SCIPvarAdjustUb(var, set, &newbound);
8069 
8070  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8071 
8072  /* change bounds of attached variables */
8073  switch( SCIPvarGetStatus(var) )
8074  {
8076  assert(var->data.original.transvar != NULL);
8077  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8078  break;
8079 
8080  case SCIP_VARSTATUS_COLUMN:
8081  assert(var->data.col != NULL);
8082  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8083  break;
8084 
8085  case SCIP_VARSTATUS_LOOSE:
8086  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8087  return SCIP_INVALIDDATA;
8088 
8089  case SCIP_VARSTATUS_FIXED:
8090  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8091  return SCIP_INVALIDDATA;
8092 
8093  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8094  assert(var->data.aggregate.var != NULL);
8095  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8096  {
8097  SCIP_Real childnewbound;
8098 
8099  /* a > 0 -> change upper bound of y */
8100  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8101  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8102  else
8103  childnewbound = newbound;
8104  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8105  }
8106  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8107  {
8108  SCIP_Real childnewbound;
8109 
8110  /* a < 0 -> change lower bound of y */
8111  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8112  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8113  else
8114  childnewbound = -newbound;
8115  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8116  }
8117  else
8118  {
8119  SCIPerrorMessage("scalar is zero in aggregation\n");
8120  return SCIP_INVALIDDATA;
8121  }
8122  break;
8123 
8125  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8126  return SCIP_INVALIDDATA;
8127 
8128  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8129  assert(var->negatedvar != NULL);
8131  assert(var->negatedvar->negatedvar == var);
8132  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8133  break;
8134 
8135  default:
8136  SCIPerrorMessage("unknown variable status\n");
8137  return SCIP_INVALIDDATA;
8138  }
8139 
8140  return SCIP_OKAY;
8141 }
8142 
8143 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8144  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8145  * not updated if bounds of aggregation variables are changing
8146  *
8147  * calling this function for a non-multi-aggregated variable is not allowed
8148  */
8150  SCIP_VAR* var, /**< problem variable */
8151  SCIP_SET* set /**< global SCIP settings */
8152  )
8153 {
8154  int i;
8155  SCIP_Real lb;
8156  SCIP_Real bnd;
8157  SCIP_VAR* aggrvar;
8158  SCIP_Bool posinf;
8159  SCIP_Bool neginf;
8160 
8161  assert(var != NULL);
8162  assert(set != NULL);
8163  assert(var->scip == set->scip);
8165 
8166  posinf = FALSE;
8167  neginf = FALSE;
8168  lb = var->data.multaggr.constant;
8169  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8170  {
8171  aggrvar = var->data.multaggr.vars[i];
8172  if( var->data.multaggr.scalars[i] > 0.0 )
8173  {
8174  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8175 
8176  if( SCIPsetIsInfinity(set, bnd) )
8177  posinf = TRUE;
8178  else if( SCIPsetIsInfinity(set, -bnd) )
8179  neginf = TRUE;
8180  else
8181  lb += var->data.multaggr.scalars[i] * bnd;
8182  }
8183  else
8184  {
8185  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8186 
8187  if( SCIPsetIsInfinity(set, -bnd) )
8188  posinf = TRUE;
8189  else if( SCIPsetIsInfinity(set, bnd) )
8190  neginf = TRUE;
8191  else
8192  lb += var->data.multaggr.scalars[i] * bnd;
8193  }
8194 
8195  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8196  * variable
8197  */
8198  if( neginf )
8199  return SCIPvarGetLbLocal(var);
8200  }
8201 
8202  /* if positive infinity flag was set to true return infinity */
8203  if( posinf )
8204  return SCIPsetInfinity(set);
8205 
8206  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8207 }
8208 
8209 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8210  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8211  * not updated if bounds of aggregation variables are changing
8212  *
8213  * calling this function for a non-multi-aggregated variable is not allowed
8214  */
8216  SCIP_VAR* var, /**< problem variable */
8217  SCIP_SET* set /**< global SCIP settings */
8218  )
8219 {
8220  int i;
8221  SCIP_Real ub;
8222  SCIP_Real bnd;
8223  SCIP_VAR* aggrvar;
8224  SCIP_Bool posinf;
8225  SCIP_Bool neginf;
8226 
8227  assert(var != NULL);
8228  assert(set != NULL);
8229  assert(var->scip == set->scip);
8231 
8232  posinf = FALSE;
8233  neginf = FALSE;
8234  ub = var->data.multaggr.constant;
8235  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8236  {
8237  aggrvar = var->data.multaggr.vars[i];
8238  if( var->data.multaggr.scalars[i] > 0.0 )
8239  {
8240  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8241 
8242  if( SCIPsetIsInfinity(set, bnd) )
8243  posinf = TRUE;
8244  else if( SCIPsetIsInfinity(set, -bnd) )
8245  neginf = TRUE;
8246  else
8247  ub += var->data.multaggr.scalars[i] * bnd;
8248  }
8249  else
8250  {
8251  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8252 
8253  if( SCIPsetIsInfinity(set, -bnd) )
8254  posinf = TRUE;
8255  else if( SCIPsetIsInfinity(set, bnd) )
8256  neginf = TRUE;
8257  else
8258  ub += var->data.multaggr.scalars[i] * bnd;
8259  }
8260 
8261  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8262  * variable
8263  */
8264  if( posinf )
8265  return SCIPvarGetUbLocal(var);
8266  }
8267 
8268  /* if negative infinity flag was set to true return -infinity */
8269  if( neginf )
8270  return -SCIPsetInfinity(set);
8271 
8272  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8273 }
8274 
8275 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8276  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8277  * not updated if bounds of aggregation variables are changing
8278  *
8279  * calling this function for a non-multi-aggregated variable is not allowed
8280  */
8282  SCIP_VAR* var, /**< problem variable */
8283  SCIP_SET* set /**< global SCIP settings */
8284  )
8285 {
8286  int i;
8287  SCIP_Real lb;
8288  SCIP_Real bnd;
8289  SCIP_VAR* aggrvar;
8290  SCIP_Bool posinf;
8291  SCIP_Bool neginf;
8292 
8293  assert(var != NULL);
8294  assert(set != NULL);
8295  assert(var->scip == set->scip);
8297 
8298  posinf = FALSE;
8299  neginf = FALSE;
8300  lb = var->data.multaggr.constant;
8301  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8302  {
8303  aggrvar = var->data.multaggr.vars[i];
8304  if( var->data.multaggr.scalars[i] > 0.0 )
8305  {
8306  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8307 
8308  if( SCIPsetIsInfinity(set, bnd) )
8309  posinf = TRUE;
8310  else if( SCIPsetIsInfinity(set, -bnd) )
8311  neginf = TRUE;
8312  else
8313  lb += var->data.multaggr.scalars[i] * bnd;
8314  }
8315  else
8316  {
8317  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8318 
8319  if( SCIPsetIsInfinity(set, -bnd) )
8320  posinf = TRUE;
8321  else if( SCIPsetIsInfinity(set, bnd) )
8322  neginf = TRUE;
8323  else
8324  lb += var->data.multaggr.scalars[i] * bnd;
8325  }
8326 
8327  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8328  * variable
8329  */
8330  if( neginf )
8331  return SCIPvarGetLbGlobal(var);
8332  }
8333 
8334  /* if positive infinity flag was set to true return infinity */
8335  if( posinf )
8336  return SCIPsetInfinity(set);
8337 
8338  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8339 }
8340 
8341 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8342  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8343  * not updated if bounds of aggregation variables are changing
8344  *
8345  * calling this function for a non-multi-aggregated variable is not allowed
8346  */
8348  SCIP_VAR* var, /**< problem variable */
8349  SCIP_SET* set /**< global SCIP settings */
8350  )
8351 {
8352  int i;
8353  SCIP_Real ub;
8354  SCIP_Real bnd;
8355  SCIP_VAR* aggrvar;
8356  SCIP_Bool posinf;
8357  SCIP_Bool neginf;
8358 
8359  assert(var != NULL);
8360  assert(set != NULL);
8361  assert(var->scip == set->scip);
8363 
8364  posinf = FALSE;
8365  neginf = FALSE;
8366  ub = var->data.multaggr.constant;
8367  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8368  {
8369  aggrvar = var->data.multaggr.vars[i];
8370  if( var->data.multaggr.scalars[i] > 0.0 )
8371  {
8372  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8373 
8374  if( SCIPsetIsInfinity(set, bnd) )
8375  posinf = TRUE;
8376  else if( SCIPsetIsInfinity(set, -bnd) )
8377  neginf = TRUE;
8378  else
8379  ub += var->data.multaggr.scalars[i] * bnd;
8380  }
8381  else
8382  {
8383  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8384 
8385  if( SCIPsetIsInfinity(set, -bnd) )
8386  posinf = TRUE;
8387  else if( SCIPsetIsInfinity(set, bnd) )
8388  neginf = TRUE;
8389  else
8390  ub += var->data.multaggr.scalars[i] * bnd;
8391  }
8392 
8393  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8394  * variable
8395  */
8396  if( posinf )
8397  return SCIPvarGetUbGlobal(var);
8398  }
8399 
8400  /* if negative infinity flag was set to true return -infinity */
8401  if( neginf )
8402  return -SCIPsetInfinity(set);
8403 
8404  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8405 }
8406 
8407 /** adds a hole to the original domain of the variable */
8409  SCIP_VAR* var, /**< problem variable */
8410  BMS_BLKMEM* blkmem, /**< block memory */
8411  SCIP_SET* set, /**< global SCIP settings */
8412  SCIP_Real left, /**< left bound of open interval in new hole */
8413  SCIP_Real right /**< right bound of open interval in new hole */
8414  )
8415 {
8416  SCIP_Bool added;
8417 
8418  assert(var != NULL);
8419  assert(!SCIPvarIsTransformed(var));
8421  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8422  assert(set != NULL);
8423  assert(var->scip == set->scip);
8424  assert(set->stage == SCIP_STAGE_PROBLEM);
8425 
8426  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8427 
8428  if( SCIPsetIsEQ(set, left, right) )
8429  return SCIP_OKAY;
8430 
8431  /* the interval should not be empty */
8432  assert(SCIPsetIsLT(set, left, right));
8433 
8434  /* the the interval bound should already be adjusted */
8435  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8436  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8437 
8438  /* the the interval should lay between the lower and upper bound */
8439  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8440  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8441 
8442  /* add domain hole */
8443  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8444 
8445  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8446  if( added )
8447  {
8448  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8449  }
8450 
8451  /**@todo add hole in parent and child variables (just like with bound changes);
8452  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8453  */
8454 
8455  return SCIP_OKAY;
8456 }
8457 
8458 /** performs the current add of domain, changes all parents accordingly */
8459 static
8461  SCIP_VAR* var, /**< problem variable */
8462  BMS_BLKMEM* blkmem, /**< block memory */
8463  SCIP_SET* set, /**< global SCIP settings */
8464  SCIP_STAT* stat, /**< problem statistics */
8465  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8466  SCIP_Real left, /**< left bound of open interval in new hole */
8467  SCIP_Real right, /**< right bound of open interval in new hole */
8468  SCIP_Bool* added /**< pointer to store whether the hole was added */
8469  )
8470 {
8471  SCIP_VAR* parentvar;
8472  SCIP_Real newlb;
8473  SCIP_Real newub;
8474  int i;
8475 
8476  assert(var != NULL);
8477  assert(added != NULL);
8478  assert(blkmem != NULL);
8479 
8480  /* the interval should not be empty */
8481  assert(SCIPsetIsLT(set, left, right));
8482 
8483  /* the interval bound should already be adjusted */
8484  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8485  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8486 
8487  /* the interval should lay between the lower and upper bound */
8488  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8489  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8490 
8491  /* @todo add debugging mechanism for holes when using a debugging solution */
8492 
8493  /* add hole to hole list */
8494  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8495 
8496  /* check if the hole is redundant */
8497  if( !(*added) )
8498  return SCIP_OKAY;
8499 
8500  /* current bounds */
8501  newlb = var->glbdom.lb;
8502  newub = var->glbdom.ub;
8503 
8504  /* merge domain holes */
8505  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8506 
8507  /* the bound should not be changed */
8508  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8509  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8510 
8511  /* issue bound change event */
8512  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8513  if( var->eventfilter != NULL )
8514  {
8515  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8516  }
8517 
8518  /* process parent variables */
8519  for( i = 0; i < var->nparentvars; ++i )
8520  {
8521  SCIP_Real parentnewleft;
8522  SCIP_Real parentnewright;
8523  SCIP_Bool localadded;
8524 
8525  parentvar = var->parentvars[i];
8526  assert(parentvar != NULL);
8527 
8528  switch( SCIPvarGetStatus(parentvar) )
8529  {
8531  parentnewleft = left;
8532  parentnewright = right;
8533  break;
8534 
8535  case SCIP_VARSTATUS_COLUMN:
8536  case SCIP_VARSTATUS_LOOSE:
8537  case SCIP_VARSTATUS_FIXED:
8539  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8540  return SCIP_INVALIDDATA;
8541 
8542  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8543  assert(parentvar->data.aggregate.var == var);
8544 
8545  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8546  {
8547  /* a > 0 -> change upper bound of x */
8548  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8549  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8550  }
8551  else
8552  {
8553  /* a < 0 -> change lower bound of x */
8554  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8555 
8556  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8557  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8558  }
8559  break;
8560 
8561  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8562  assert(parentvar->negatedvar != NULL);
8563  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8564  assert(parentvar->negatedvar->negatedvar == parentvar);
8565 
8566  parentnewright = -left + parentvar->data.negate.constant;
8567  parentnewleft = -right + parentvar->data.negate.constant;
8568  break;
8569 
8570  default:
8571  SCIPerrorMessage("unknown variable status\n");
8572  return SCIP_INVALIDDATA;
8573  }
8574 
8575  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8576 
8577  /* perform hole added for parent variable */
8578  assert(blkmem != NULL);
8579  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8580  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8581  parentnewleft, parentnewright, &localadded) );
8582  assert(localadded);
8583  }
8584 
8585  return SCIP_OKAY;
8586 }
8587 
8588 /** adds a hole to the variable's global and local domain */
8590  SCIP_VAR* var, /**< problem variable */
8591  BMS_BLKMEM* blkmem, /**< block memory */
8592  SCIP_SET* set, /**< global SCIP settings */
8593  SCIP_STAT* stat, /**< problem statistics */
8594  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8595  SCIP_Real left, /**< left bound of open interval in new hole */
8596  SCIP_Real right, /**< right bound of open interval in new hole */
8597  SCIP_Bool* added /**< pointer to store whether the hole was added */
8598  )
8599 {
8600  SCIP_Real childnewleft;
8601  SCIP_Real childnewright;
8602 
8603  assert(var != NULL);
8604  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8605  assert(blkmem != NULL);
8606  assert(added != NULL);
8607 
8608  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8609 
8610  /* the interval should not be empty */
8611  assert(SCIPsetIsLT(set, left, right));
8612 
8613  /* the the interval bound should already be adjusted */
8614  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8615  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8616 
8617  /* the the interval should lay between the lower and upper bound */
8618  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8619  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8620 
8621  /* change bounds of attached variables */
8622  switch( SCIPvarGetStatus(var) )
8623  {
8625  if( var->data.original.transvar != NULL )
8626  {
8627  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8628  left, right, added) );
8629  }
8630  else
8631  {
8632  assert(set->stage == SCIP_STAGE_PROBLEM);
8633 
8634  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8635  if( *added )
8636  {
8637  SCIP_Bool localadded;
8638 
8639  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8640  }
8641  }
8642  break;
8643 
8644  case SCIP_VARSTATUS_COLUMN:
8645  case SCIP_VARSTATUS_LOOSE:
8646  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8647  if( *added )
8648  {
8649  SCIP_Bool localadded;
8650 
8651  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8652  }
8653  break;
8654 
8655  case SCIP_VARSTATUS_FIXED:
8656  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8657  return SCIP_INVALIDDATA;
8658 
8659  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8660  assert(var->data.aggregate.var != NULL);
8661 
8662  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8663  {
8664  /* a > 0 -> change lower bound of y */
8665  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8666  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8667  }
8668  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8669  {
8670  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8671  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8672  }
8673  else
8674  {
8675  SCIPerrorMessage("scalar is zero in aggregation\n");
8676  return SCIP_INVALIDDATA;
8677  }
8678  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8679  childnewleft, childnewright, added) );
8680  break;
8681 
8683  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8684  return SCIP_INVALIDDATA;
8685 
8686  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8687  assert(var->negatedvar != NULL);
8689  assert(var->negatedvar->negatedvar == var);
8690 
8691  childnewright = -left + var->data.negate.constant;
8692  childnewleft = -right + var->data.negate.constant;
8693 
8694  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8695  childnewleft, childnewright, added) );
8696  break;
8697 
8698  default:
8699  SCIPerrorMessage("unknown variable status\n");
8700  return SCIP_INVALIDDATA;
8701  }
8702 
8703  return SCIP_OKAY;
8704 }
8705 
8706 /** performs the current add of domain, changes all parents accordingly */
8707 static
8709  SCIP_VAR* var, /**< problem variable */
8710  BMS_BLKMEM* blkmem, /**< block memory */
8711  SCIP_SET* set, /**< global SCIP settings */
8712  SCIP_STAT* stat, /**< problem statistics */
8713  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8714  SCIP_Real left, /**< left bound of open interval in new hole */
8715  SCIP_Real right, /**< right bound of open interval in new hole */
8716  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8717  )
8718 {
8719  SCIP_VAR* parentvar;
8720  SCIP_Real newlb;
8721  SCIP_Real newub;
8722  int i;
8723 
8724  assert(var != NULL);
8725  assert(added != NULL);
8726  assert(blkmem != NULL);
8727 
8728  /* the interval should not be empty */
8729  assert(SCIPsetIsLT(set, left, right));
8730 
8731  /* the the interval bound should already be adjusted */
8732  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8733  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8734 
8735  /* the the interval should lay between the lower and upper bound */
8736  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8737  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8738 
8739  /* add hole to hole list */
8740  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8741 
8742  /* check if the hole is redundant */
8743  if( !(*added) )
8744  return SCIP_OKAY;
8745 
8746  /* current bounds */
8747  newlb = var->locdom.lb;
8748  newub = var->locdom.ub;
8749 
8750  /* merge domain holes */
8751  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8752 
8753  /* the bound should not be changed */
8754  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8755  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8756 
8757 #if 0
8758  /* issue bound change event */
8759  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8760  if( var->eventfilter != NULL )
8761  {
8762  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8763  }
8764 #endif
8765 
8766  /* process parent variables */
8767  for( i = 0; i < var->nparentvars; ++i )
8768  {
8769  SCIP_Real parentnewleft;
8770  SCIP_Real parentnewright;
8771  SCIP_Bool localadded;
8772 
8773  parentvar = var->parentvars[i];
8774  assert(parentvar != NULL);
8775 
8776  switch( SCIPvarGetStatus(parentvar) )
8777  {
8779  parentnewleft = left;
8780  parentnewright = right;
8781  break;
8782 
8783  case SCIP_VARSTATUS_COLUMN:
8784  case SCIP_VARSTATUS_LOOSE:
8785  case SCIP_VARSTATUS_FIXED:
8787  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8788  return SCIP_INVALIDDATA;
8789 
8790  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8791  assert(parentvar->data.aggregate.var == var);
8792 
8793  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8794  {
8795  /* a > 0 -> change upper bound of x */
8796  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8797  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8798  }
8799  else
8800  {
8801  /* a < 0 -> change lower bound of x */
8802  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8803 
8804  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8805  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8806  }
8807  break;
8808 
8809  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8810  assert(parentvar->negatedvar != NULL);
8811  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8812  assert(parentvar->negatedvar->negatedvar == parentvar);
8813 
8814  parentnewright = -left + parentvar->data.negate.constant;
8815  parentnewleft = -right + parentvar->data.negate.constant;
8816  break;
8817 
8818  default:
8819  SCIPerrorMessage("unknown variable status\n");
8820  return SCIP_INVALIDDATA;
8821  }
8822 
8823  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8824 
8825  /* perform hole added for parent variable */
8826  assert(blkmem != NULL);
8827  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8828  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8829  parentnewleft, parentnewright, &localadded) );
8830  assert(localadded);
8831  }
8832 
8833  return SCIP_OKAY;
8834 }
8835 
8836 /** adds a hole to the variable's current local domain */
8838  SCIP_VAR* var, /**< problem variable */
8839  BMS_BLKMEM* blkmem, /**< block memory */
8840  SCIP_SET* set, /**< global SCIP settings */
8841  SCIP_STAT* stat, /**< problem statistics */
8842  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8843  SCIP_Real left, /**< left bound of open interval in new hole */
8844  SCIP_Real right, /**< right bound of open interval in new hole */
8845  SCIP_Bool* added /**< pointer to store whether the hole was added */
8846  )
8847 {
8848  SCIP_Real childnewleft;
8849  SCIP_Real childnewright;
8850 
8851  assert(var != NULL);
8852 
8853  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8854 
8855  assert(set != NULL);
8856  assert(var->scip == set->scip);
8857  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8858  assert(blkmem != NULL);
8859  assert(added != NULL);
8860 
8861  /* the interval should not be empty */
8862  assert(SCIPsetIsLT(set, left, right));
8863 
8864  /* the the interval bound should already be adjusted */
8865  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8866  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8867 
8868  /* the the interval should lay between the lower and upper bound */
8869  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8870  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8871 
8872  /* change bounds of attached variables */
8873  switch( SCIPvarGetStatus(var) )
8874  {
8876  if( var->data.original.transvar != NULL )
8877  {
8878  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8879  left, right, added) );
8880  }
8881  else
8882  {
8883  assert(set->stage == SCIP_STAGE_PROBLEM);
8884  SCIPstatIncrement(stat, set, domchgcount);
8885  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8886  }
8887  break;
8888 
8889  case SCIP_VARSTATUS_COLUMN:
8890  case SCIP_VARSTATUS_LOOSE:
8891  SCIPstatIncrement(stat, set, domchgcount);
8892  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8893  break;
8894 
8895  case SCIP_VARSTATUS_FIXED:
8896  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8897  return SCIP_INVALIDDATA;
8898 
8899  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8900  assert(var->data.aggregate.var != NULL);
8901 
8902  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8903  {
8904  /* a > 0 -> change lower bound of y */
8905  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8906  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8907  }
8908  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8909  {
8910  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8911  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8912  }
8913  else
8914  {
8915  SCIPerrorMessage("scalar is zero in aggregation\n");
8916  return SCIP_INVALIDDATA;
8917  }
8918  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8919  childnewleft, childnewright, added) );
8920  break;
8921 
8923  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8924  return SCIP_INVALIDDATA;
8925 
8926  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8927  assert(var->negatedvar != NULL);
8929  assert(var->negatedvar->negatedvar == var);
8930 
8931  childnewright = -left + var->data.negate.constant;
8932  childnewleft = -right + var->data.negate.constant;
8933 
8934  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8935  break;
8936 
8937  default:
8938  SCIPerrorMessage("unknown variable status\n");
8939  return SCIP_INVALIDDATA;
8940  }
8941 
8942  return SCIP_OKAY;
8943 }
8944 
8945 /** resets the global and local bounds of original variable to their original values */
8947  SCIP_VAR* var, /**< problem variable */
8948  BMS_BLKMEM* blkmem, /**< block memory */
8949  SCIP_SET* set, /**< global SCIP settings */
8950  SCIP_STAT* stat /**< problem statistics */
8951  )
8952 {
8953  assert(var != NULL);
8954  assert(set != NULL);
8955  assert(var->scip == set->scip);
8956  assert(SCIPvarIsOriginal(var));
8957  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8958  * the transformed variable has been fixed */
8959  assert(SCIPvarGetTransVar(var) == NULL);
8960 
8961  /* copy the original bounds back to the global and local bounds */
8962  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8963  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8964  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8965  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8966 
8967  /* free the global and local holelists and duplicate the original ones */
8968  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8969  holelistFree(&var->glbdom.holelist, blkmem);
8970  holelistFree(&var->locdom.holelist, blkmem);
8971  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8972  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8973 
8974  return SCIP_OKAY;
8975 }
8976 
8977 /** issues a IMPLADDED event on the given variable */
8978 static
8980  SCIP_VAR* var, /**< problem variable to change */
8981  BMS_BLKMEM* blkmem, /**< block memory */
8982  SCIP_SET* set, /**< global SCIP settings */
8983  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8984  )
8985 {
8986  SCIP_EVENT* event;
8987 
8988  assert(var != NULL);
8989 
8990  /* issue IMPLADDED event on variable */
8991  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8992  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8993 
8994  return SCIP_OKAY;
8995 }
8996 
8997 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8998 static
9000  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9001  BMS_BLKMEM* blkmem, /**< block memory */
9002  SCIP_SET* set, /**< global SCIP settings */
9003  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9004  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9005  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9006  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9007  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9008  )
9009 {
9010  SCIP_Bool added;
9011 
9012  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9013  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9014  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9015  *
9016  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9017  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9018  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9019  * variable bound can be ignored.
9020  *
9021  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9022  * equivalence of the variables should be checked here.
9023  */
9024  if( var == vbvar )
9025  {
9026  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9027  * can be checked via the global bounds of the variable */
9028 #ifndef NDEBUG
9029  SCIP_Real lb;
9030  SCIP_Real ub;
9031 
9032  lb = SCIPvarGetLbGlobal(var);
9033  ub = SCIPvarGetUbGlobal(var);
9034 
9035  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9036  {
9037  if( vbcoef > 0.0 )
9038  {
9039  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9040  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9041  }
9042  else
9043  {
9044  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9045  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9046  }
9047  }
9048  else
9049  {
9050  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9051  if( vbcoef > 0.0 )
9052  {
9053  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9054  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9055  }
9056  else
9057  {
9058  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9059  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9060  }
9061  }
9062 #endif
9063  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9064  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9065 
9066  return SCIP_OKAY;
9067  }
9068 
9069  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9070  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9071 
9072  /* check variable bound on debugging solution */
9073  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9074 
9075  /* perform the addition */
9076  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9077  {
9078  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9079  }
9080  else
9081  {
9082  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9083  }
9084  var->closestvblpcount = -1;
9085 
9086  if( added )
9087  {
9088  /* issue IMPLADDED event */
9089  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9090  }
9091 
9092  return SCIP_OKAY;
9093 }
9094 
9095 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9096 static
9097 void checkImplic(
9098  SCIP_SET* set, /**< global SCIP settings */
9099  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9100  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9101  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9102  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9103  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9104  )
9105 {
9106  SCIP_Real impllb;
9107  SCIP_Real implub;
9108 
9109  assert(redundant != NULL);
9110  assert(infeasible != NULL);
9111 
9112  impllb = SCIPvarGetLbGlobal(implvar);
9113  implub = SCIPvarGetUbGlobal(implvar);
9114  if( impltype == SCIP_BOUNDTYPE_LOWER )
9115  {
9116  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9117  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9118  }
9119  else
9120  {
9121  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9122  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9123  }
9124 }
9125 
9126 /** applies the given implication, if it is not redundant */
9127 static
9129  BMS_BLKMEM* blkmem, /**< block memory */
9130  SCIP_SET* set, /**< global SCIP settings */
9131  SCIP_STAT* stat, /**< problem statistics */
9132  SCIP_PROB* transprob, /**< transformed problem */
9133  SCIP_PROB* origprob, /**< original problem */
9134  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9135  SCIP_REOPT* reopt, /**< reoptimization data structure */
9136  SCIP_LP* lp, /**< current LP data */
9137  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9138  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9139  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9140  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9141  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9142  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9143  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9144  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9145  )
9146 {
9147  SCIP_Real implub;
9148  SCIP_Real impllb;
9149 
9150  assert(infeasible != NULL);
9151 
9152  *infeasible = FALSE;
9153 
9154  implub = SCIPvarGetUbGlobal(implvar);
9155  impllb = SCIPvarGetLbGlobal(implvar);
9156  if( impltype == SCIP_BOUNDTYPE_LOWER )
9157  {
9158  if( SCIPsetIsFeasGT(set, implbound, implub) )
9159  {
9160  /* the implication produces a conflict: the problem is infeasible */
9161  *infeasible = TRUE;
9162  }
9163  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9164  {
9165  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9166  * with the local bound, in this case we need to store the bound change as pending bound change
9167  */
9168  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9169  {
9170  assert(tree != NULL);
9171  assert(transprob != NULL);
9172  assert(SCIPprobIsTransformed(transprob));
9173 
9174  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9175  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9176  }
9177  else
9178  {
9179  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9180  }
9181 
9182  if( nbdchgs != NULL )
9183  (*nbdchgs)++;
9184  }
9185  }
9186  else
9187  {
9188  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9189  {
9190  /* the implication produces a conflict: the problem is infeasible */
9191  *infeasible = TRUE;
9192  }
9193  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9194  {
9195  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9196  * with the local bound, in this case we need to store the bound change as pending bound change
9197  */
9198  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9199  {
9200  assert(tree != NULL);
9201  assert(transprob != NULL);
9202  assert(SCIPprobIsTransformed(transprob));
9203 
9204  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9205  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9206  }
9207  else
9208  {
9209  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9210  }
9211 
9212  if( nbdchgs != NULL )
9213  (*nbdchgs)++;
9214  }
9215  }
9216 
9217  return SCIP_OKAY;
9218 }
9219 
9220 /** actually performs the addition of an implication to the variable's implication arrays,
9221  * and adds the corresponding implication or variable bound to the implied variable;
9222  * if the implication is conflicting, the variable is fixed to the opposite value;
9223  * if the variable is already fixed to the given value, the implication is performed immediately;
9224  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9225  */
9226 static
9228  SCIP_VAR* var, /**< problem variable */
9229  BMS_BLKMEM* blkmem, /**< block memory */
9230  SCIP_SET* set, /**< global SCIP settings */
9231  SCIP_STAT* stat, /**< problem statistics */
9232  SCIP_PROB* transprob, /**< transformed problem */
9233  SCIP_PROB* origprob, /**< original problem */
9234  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9235  SCIP_REOPT* reopt, /**< reoptimization data structure */
9236  SCIP_LP* lp, /**< current LP data */
9237  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9238  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9239  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9240  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9241  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9242  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9243  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9244  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9245  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9246  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9247  SCIP_Bool* added /**< pointer to store whether an implication was added */
9248  )
9249 {
9250  SCIP_Bool redundant;
9251  SCIP_Bool conflict;
9252 
9253  assert(var != NULL);
9254  assert(SCIPvarIsActive(var));
9256  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9257  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9258  assert(infeasible != NULL);
9259  assert(added != NULL);
9260 
9261  /* check implication on debugging solution */
9262  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9263 
9264  *infeasible = FALSE;
9265  *added = FALSE;
9266 
9267  /* check, if the implication is redundant or infeasible */
9268  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9269  assert(!redundant || !conflict);
9270  if( redundant )
9271  return SCIP_OKAY;
9272 
9273  if( var == implvar )
9274  {
9275  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9276  * x == varfixing => x < 0 or x > 1
9277  */
9278  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9279  conflict = TRUE;
9280  else
9281  {
9282  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9283  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9284  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9285  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9286  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9287  if( !conflict )
9288  return SCIP_OKAY;
9289  }
9290  }
9291 
9292  /* check, if the variable is already fixed */
9293  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9294  {
9295  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9296  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9297  {
9298  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9299  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9300  }
9301  return SCIP_OKAY;
9302  }
9303 
9304  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9305  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9306 
9307  if( !conflict )
9308  {
9309  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9310 
9311  if( SCIPvarIsBinary(implvar) )
9312  {
9313  SCIP_VAR* vars[2];
9314  SCIP_Bool vals[2];
9315 
9316  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9317  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9318 
9319  vars[0] = var;
9320  vars[1] = implvar;
9321  vals[0] = varfixing;
9322  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9323 
9324  /* add the clique to the clique table */
9325  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9326  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9327 
9328  if( !conflict )
9329  return SCIP_OKAY;
9330  }
9331  else
9332  {
9333  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9334  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9335  SCIPvarGetName(var), varfixing,
9336  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9337  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9338  isshortcut, &conflict, added) );
9339  }
9340  }
9341  assert(!conflict || !(*added));
9342 
9343  /* on conflict, fix the variable to the opposite value */
9344  if( conflict )
9345  {
9346  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9347 
9348  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9349  * with the local bound, in this case we need to store the bound change as pending bound change
9350  */
9351  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9352  {
9353  assert(tree != NULL);
9354  assert(transprob != NULL);
9355  assert(SCIPprobIsTransformed(transprob));
9356 
9357  if( varfixing )
9358  {
9359  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9360  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9361  }
9362  else
9363  {
9364  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9365  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9366  }
9367  }
9368  else
9369  {
9370  if( varfixing )
9371  {
9372  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9373  }
9374  else
9375  {
9376  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9377  }
9378  }
9379  if( nbdchgs != NULL )
9380  (*nbdchgs)++;
9381 
9382  return SCIP_OKAY;
9383  }
9384  else if( *added )
9385  {
9386  /* issue IMPLADDED event */
9387  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9388  }
9389  else
9390  {
9391  /* the implication was redundant: the inverse is also redundant */
9392  return SCIP_OKAY;
9393  }
9394 
9395  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9396 
9397  /* check, whether implied variable is binary */
9398  if( !SCIPvarIsBinary(implvar) )
9399  {
9400  SCIP_Real lb;
9401  SCIP_Real ub;
9402 
9403  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9404  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9405  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9406  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9407  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9408  * for numerical reasons, ignore variable bounds with large absolute coefficient
9409  */
9410  lb = SCIPvarGetLbGlobal(implvar);
9411  ub = SCIPvarGetUbGlobal(implvar);
9412  if( impltype == SCIP_BOUNDTYPE_UPPER )
9413  {
9414  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9415  {
9416  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9417  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9418  }
9419  }
9420  else
9421  {
9422  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9423  {
9424  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9425  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9426  }
9427  }
9428  }
9429 
9430  return SCIP_OKAY;
9431 }
9432 
9433 /** adds transitive closure for binary implication x = a -> y = b */
9434 static
9436  SCIP_VAR* var, /**< problem variable */
9437  BMS_BLKMEM* blkmem, /**< block memory */
9438  SCIP_SET* set, /**< global SCIP settings */
9439  SCIP_STAT* stat, /**< problem statistics */
9440  SCIP_PROB* transprob, /**< transformed problem */
9441  SCIP_PROB* origprob, /**< original problem */
9442  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9443  SCIP_REOPT* reopt, /**< reoptimization data structure */
9444  SCIP_LP* lp, /**< current LP data */
9445  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9446  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9447  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9448  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9449  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9450  SCIP_Bool implvarfixing, /**< fixing b in implication */
9451  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9452  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9453  )
9454 {
9455  SCIP_VAR** implvars;
9456  SCIP_BOUNDTYPE* impltypes;
9457  SCIP_Real* implbounds;
9458  int nimpls;
9459  int i;
9460 
9461  *infeasible = FALSE;
9462 
9463  /* binary variable: implications of implvar */
9464  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9465  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9466  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9467  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9468 
9469  /* if variable has too many implications, the implication graph may become too dense */
9470  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9471 
9472  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9473  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9474  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9475  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9476  * only thing that can happen is that we add the same implication twice - this does no harm
9477  */
9478  while ( i >= 0 && !(*infeasible) )
9479  {
9480  SCIP_Bool added;
9481 
9482  assert(implvars[i] != implvar);
9483 
9484  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9485  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9486  */
9487  if( SCIPvarIsActive(implvars[i]) )
9488  {
9489  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9490  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9491  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9492  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9493  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9494  }
9495  --i;
9496  }
9497 
9498  return SCIP_OKAY;
9499 }
9500 
9501 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9502  * implication to the variable's implication list;
9503  * if the implication is conflicting, the variable is fixed to the opposite value;
9504  * if the variable is already fixed to the given value, the implication is performed immediately;
9505  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9506  */
9507 static
9509  SCIP_VAR* var, /**< problem variable */
9510  BMS_BLKMEM* blkmem, /**< block memory */
9511  SCIP_SET* set, /**< global SCIP settings */
9512  SCIP_STAT* stat, /**< problem statistics */
9513  SCIP_PROB* transprob, /**< transformed problem */
9514  SCIP_PROB* origprob, /**< original problem */
9515  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9516  SCIP_REOPT* reopt, /**< reoptimization data structure */
9517  SCIP_LP* lp, /**< current LP data */
9518  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9519  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9520  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9521  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9522  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9523  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9524  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9525  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9526  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9527  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9528  )
9529 {
9530  SCIP_Bool added;
9531 
9532  assert(var != NULL);
9533  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9534  assert(SCIPvarIsActive(var));
9535  assert(implvar != NULL);
9536  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9537  assert(infeasible != NULL);
9538 
9539  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9540  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9541  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9542 
9543  if( *infeasible || var == implvar || !transitive || !added )
9544  return SCIP_OKAY;
9545 
9546  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9547 
9548  /* add transitive closure */
9549  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9550  {
9551  SCIP_Bool implvarfixing;
9552 
9553  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9554 
9555  /* binary variable: implications of implvar */
9556  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9557  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9558 
9559  /* inverse implication */
9560  if( !(*infeasible) )
9561  {
9562  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9563  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9564  }
9565  }
9566  else
9567  {
9568  /* non-binary variable: variable lower bounds of implvar */
9569  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9570  {
9571  SCIP_VAR** vlbvars;
9572  SCIP_Real* vlbcoefs;
9573  SCIP_Real* vlbconstants;
9574  int nvlbvars;
9575  int i;
9576 
9577  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9578  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9579  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9580  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9581 
9582  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9583  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9584  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9585  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9586  * is that we add the same implication twice - this does no harm
9587  */
9588  i = nvlbvars-1;
9589  while ( i >= 0 && !(*infeasible) )
9590  {
9591  assert(vlbvars[i] != implvar);
9592  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9593 
9594  /* we have x == varfixing -> y <= b and y >= c*z + d:
9595  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9596  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9597  *
9598  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9599  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9600  * aggregation variable (the one which will stay active);
9601  *
9602  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9603  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9604  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9605  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9606  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9607  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9608  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9609  * have to explicitly check that the active variable has not a variable status
9610  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9611  */
9612  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9613  {
9614  SCIP_Real vbimplbound;
9615 
9616  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9617  if( vlbcoefs[i] >= 0.0 )
9618  {
9619  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9620  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9621  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9622  infeasible, nbdchgs, &added) );
9623  }
9624  else
9625  {
9626  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9627  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9628  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9629  infeasible, nbdchgs, &added) );
9630  }
9631  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9632  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9633  }
9634  --i;
9635  }
9636  }
9637 
9638  /* non-binary variable: variable upper bounds of implvar */
9639  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9640  {
9641  SCIP_VAR** vubvars;
9642  SCIP_Real* vubcoefs;
9643  SCIP_Real* vubconstants;
9644  int nvubvars;
9645  int i;
9646 
9647  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9648  vubvars = SCIPvboundsGetVars(implvar->vubs);
9649  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9650  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9651 
9652  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9653  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9654  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9655  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9656  * is that we add the same implication twice - this does no harm
9657  */
9658  i = nvubvars-1;
9659  while ( i >= 0 && !(*infeasible) )
9660  {
9661  assert(vubvars[i] != implvar);
9662  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9663 
9664  /* we have x == varfixing -> y >= b and y <= c*z + d:
9665  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9666  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9667  *
9668  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9669  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9670  * aggregation variable (the one which will stay active);
9671  *
9672  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9673  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9674  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9675  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9676  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9677  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9678  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9679  * have to explicitly check that the active variable has not a variable status
9680  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9681  */
9682  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9683  {
9684  SCIP_Real vbimplbound;
9685 
9686  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9687  if( vubcoefs[i] >= 0.0 )
9688  {
9689  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9690  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9691  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9692  infeasible, nbdchgs, &added) );
9693  }
9694  else
9695  {
9696  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9697  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9698  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9699  infeasible, nbdchgs, &added) );
9700  }
9701  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9702  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9703  }
9704  --i;
9705  }
9706  }
9707  }
9708 
9709  return SCIP_OKAY;
9710 }
9711 
9712 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9713  * if z is binary, the corresponding valid implication for z is also added;
9714  * improves the global bounds of the variable and the vlb variable if possible
9715  */
9717  SCIP_VAR* var, /**< problem variable */
9718  BMS_BLKMEM* blkmem, /**< block memory */
9719  SCIP_SET* set, /**< global SCIP settings */
9720  SCIP_STAT* stat, /**< problem statistics */
9721  SCIP_PROB* transprob, /**< transformed problem */
9722  SCIP_PROB* origprob, /**< original problem */
9723  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9724  SCIP_REOPT* reopt, /**< reoptimization data structure */
9725  SCIP_LP* lp, /**< current LP data */
9726  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9727  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9728  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9729  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9730  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9731  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9732  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9733  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9734  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9735  )
9736 {
9737  assert(var != NULL);
9738  assert(set != NULL);
9739  assert(var->scip == set->scip);
9740  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9741  assert(infeasible != NULL);
9742 
9743  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9744 
9745  *infeasible = FALSE;
9746  if( nbdchgs != NULL )
9747  *nbdchgs = 0;
9748 
9749  switch( SCIPvarGetStatus(var) )
9750  {
9752  assert(var->data.original.transvar != NULL);
9753  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9754  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9755  break;
9756 
9757  case SCIP_VARSTATUS_COLUMN:
9758  case SCIP_VARSTATUS_LOOSE:
9759  case SCIP_VARSTATUS_FIXED:
9760  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9761  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9762  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9763 
9764  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9765  if( SCIPsetIsZero(set, vlbcoef) )
9766  {
9767  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9768  *infeasible = TRUE;
9769  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9770  {
9771  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9772  * with the local bound, in this case we need to store the bound change as pending bound change
9773  */
9774  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9775  {
9776  assert(tree != NULL);
9777  assert(transprob != NULL);
9778  assert(SCIPprobIsTransformed(transprob));
9779 
9780  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9781  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9782  }
9783  else
9784  {
9785  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9786  }
9787 
9788  if( nbdchgs != NULL )
9789  (*nbdchgs)++;
9790  }
9791  }
9792  else if( SCIPvarIsActive(vlbvar) )
9793  {
9794  SCIP_Real xlb;
9795  SCIP_Real xub;
9796  SCIP_Real zlb;
9797  SCIP_Real zub;
9798  SCIP_Real minvlb;
9799  SCIP_Real maxvlb;
9800 
9802  assert(vlbcoef != 0.0);
9803 
9804  minvlb = -SCIPsetInfinity(set);
9805  maxvlb = SCIPsetInfinity(set);
9806 
9807  xlb = SCIPvarGetLbGlobal(var);
9808  xub = SCIPvarGetUbGlobal(var);
9809  zlb = SCIPvarGetLbGlobal(vlbvar);
9810  zub = SCIPvarGetUbGlobal(vlbvar);
9811 
9812  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9813  if( vlbcoef >= 0.0 )
9814  {
9815  SCIP_Real newzub;
9816 
9817  if( !SCIPsetIsInfinity(set, xub) )
9818  {
9819  /* x >= b*z + d -> z <= (x-d)/b */
9820  newzub = (xub - vlbconstant)/vlbcoef;
9821 
9822  /* return if the new bound is less than -infinity */
9823  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9824  return SCIP_OKAY;
9825 
9826  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9827  {
9828  *infeasible = TRUE;
9829  return SCIP_OKAY;
9830  }
9831  if( SCIPsetIsFeasLT(set, newzub, zub) )
9832  {
9833  /* bound might be adjusted due to integrality condition */
9834  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9835 
9836  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9837  * with the local bound, in this case we need to store the bound change as pending bound change
9838  */
9839  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9840  {
9841  assert(tree != NULL);
9842  assert(transprob != NULL);
9843  assert(SCIPprobIsTransformed(transprob));
9844 
9845  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9846  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9847  }
9848  else
9849  {
9850  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9851  }
9852  zub = newzub;
9853 
9854  if( nbdchgs != NULL )
9855  (*nbdchgs)++;
9856  }
9857  maxvlb = vlbcoef * zub + vlbconstant;
9858  if( !SCIPsetIsInfinity(set, -zlb) )
9859  minvlb = vlbcoef * zlb + vlbconstant;
9860  }
9861  else
9862  {
9863  if( !SCIPsetIsInfinity(set, zub) )
9864  maxvlb = vlbcoef * zub + vlbconstant;
9865  if( !SCIPsetIsInfinity(set, -zlb) )
9866  minvlb = vlbcoef * zlb + vlbconstant;
9867  }
9868  }
9869  else
9870  {
9871  SCIP_Real newzlb;
9872 
9873  if( !SCIPsetIsInfinity(set, xub) )
9874  {
9875  /* x >= b*z + d -> z >= (x-d)/b */
9876  newzlb = (xub - vlbconstant)/vlbcoef;
9877 
9878  /* return if the new bound is larger than infinity */
9879  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9880  return SCIP_OKAY;
9881 
9882  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9883  {
9884  *infeasible = TRUE;
9885  return SCIP_OKAY;
9886  }
9887  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9888  {
9889  /* bound might be adjusted due to integrality condition */
9890  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9891 
9892  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9893  * with the local bound, in this case we need to store the bound change as pending bound change
9894  */
9895  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9896  {
9897  assert(tree != NULL);
9898  assert(transprob != NULL);
9899  assert(SCIPprobIsTransformed(transprob));
9900 
9901  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9902  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9903  }
9904  else
9905  {
9906  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9907  }
9908  zlb = newzlb;
9909 
9910  if( nbdchgs != NULL )
9911  (*nbdchgs)++;
9912  }
9913  maxvlb = vlbcoef * zlb + vlbconstant;
9914  if( !SCIPsetIsInfinity(set, zub) )
9915  minvlb = vlbcoef * zub + vlbconstant;
9916  }
9917  else
9918  {
9919  if( !SCIPsetIsInfinity(set, -zlb) )
9920  maxvlb = vlbcoef * zlb + vlbconstant;
9921  if( !SCIPsetIsInfinity(set, zub) )
9922  minvlb = vlbcoef * zub + vlbconstant;
9923  }
9924  }
9925  if( maxvlb < minvlb )
9926  maxvlb = minvlb;
9927 
9928  /* adjust bounds due to integrality of variable */
9929  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9930  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9931 
9932  /* check bounds for feasibility */
9933  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9934  {
9935  *infeasible = TRUE;
9936  return SCIP_OKAY;
9937  }
9938  /* improve global lower bound of variable */
9939  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9940  {
9941  /* bound might be adjusted due to integrality condition */
9942  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9943 
9944  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9945  * with the local bound, in this case we need to store the bound change as pending bound change
9946  */
9947  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9948  {
9949  assert(tree != NULL);
9950  assert(transprob != NULL);
9951  assert(SCIPprobIsTransformed(transprob));
9952 
9953  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9954  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9955  }
9956  else
9957  {
9958  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9959  }
9960  xlb = minvlb;
9961 
9962  if( nbdchgs != NULL )
9963  (*nbdchgs)++;
9964  }
9965  minvlb = xlb;
9966 
9967  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9968  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9969  {
9970  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9971  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9972  */
9973 
9974  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9975 
9976  if( vlbcoef >= 0.0 )
9977  {
9978  vlbcoef = maxvlb - minvlb;
9979  vlbconstant = minvlb;
9980  }
9981  else
9982  {
9983  vlbcoef = minvlb - maxvlb;
9984  vlbconstant = maxvlb;
9985  }
9986  }
9987 
9988  /* add variable bound to the variable bounds list */
9989  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9990  {
9991  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9992  assert(!SCIPsetIsZero(set, vlbcoef));
9993 
9994  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9995  * list, thereby also adding the variable bound (or implication) to the other variable
9996  */
9997  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9998  {
9999  /* add corresponding implication:
10000  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10001  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10002  */
10003  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10004  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10005  infeasible, nbdchgs) );
10006  }
10007  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10008  {
10009  /* add corresponding implication:
10010  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10011  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10012  */
10013  SCIP_Real implbound;
10014  implbound = -vlbconstant/vlbcoef;
10015 
10016  /* tighten the implication bound if the variable is integer */
10017  if( SCIPvarIsIntegral(vlbvar) )
10018  {
10019  if( vlbcoef >= 0 )
10020  implbound = SCIPsetFloor(set, implbound);
10021  else
10022  implbound = SCIPsetCeil(set, implbound);
10023  }
10024  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10025  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10026  implbound, transitive, infeasible, nbdchgs) );
10027  }
10028  else
10029  {
10030  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10031  }
10032  }
10033  }
10034  break;
10035 
10037  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10038  * y <= b/a * z + (d-c)/a, if a < 0
10039  */
10040  assert(var->data.aggregate.var != NULL);
10041  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10042  {
10043  /* a > 0 -> add variable lower bound */
10044  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10045  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10046  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10047  }
10048  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10049  {
10050  /* a < 0 -> add variable upper bound */
10051  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10052  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10053  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10054  }
10055  else
10056  {
10057  SCIPerrorMessage("scalar is zero in aggregation\n");
10058  return SCIP_INVALIDDATA;
10059  }
10060  break;
10061 
10063  /* nothing to do here */
10064  break;
10065 
10067  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10068  assert(var->negatedvar != NULL);
10070  assert(var->negatedvar->negatedvar == var);
10071  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10072  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10073  nbdchgs) );
10074  break;
10075 
10076  default:
10077  SCIPerrorMessage("unknown variable status\n");
10078  return SCIP_INVALIDDATA;
10079  }
10080 
10081  return SCIP_OKAY;
10082 }
10083 
10084 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10085  * if z is binary, the corresponding valid implication for z is also added;
10086  * updates the global bounds of the variable and the vub variable correspondingly
10087  */
10089  SCIP_VAR* var, /**< problem variable */
10090  BMS_BLKMEM* blkmem, /**< block memory */
10091  SCIP_SET* set, /**< global SCIP settings */
10092  SCIP_STAT* stat, /**< problem statistics */
10093  SCIP_PROB* transprob, /**< transformed problem */
10094  SCIP_PROB* origprob, /**< original problem */
10095  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10096  SCIP_REOPT* reopt, /**< reoptimization data structure */
10097  SCIP_LP* lp, /**< current LP data */
10098  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10099  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10100  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10101  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10102  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10103  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10104  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10105  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10106  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10107  )
10108 {
10109  assert(var != NULL);
10110  assert(set != NULL);
10111  assert(var->scip == set->scip);
10112  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10113  assert(infeasible != NULL);
10114 
10115  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10116 
10117  *infeasible = FALSE;
10118  if( nbdchgs != NULL )
10119  *nbdchgs = 0;
10120 
10121  switch( SCIPvarGetStatus(var) )
10122  {
10124  assert(var->data.original.transvar != NULL);
10125  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10126  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10127  break;
10128 
10129  case SCIP_VARSTATUS_COLUMN:
10130  case SCIP_VARSTATUS_LOOSE:
10131  case SCIP_VARSTATUS_FIXED:
10132  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10133  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10134  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10135  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10136 
10137  /* if the vub coefficient is zero, just update the upper bound of the variable */
10138  if( SCIPsetIsZero(set, vubcoef) )
10139  {
10140  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10141  *infeasible = TRUE;
10142  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10143  {
10144  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10145  * with the local bound, in this case we need to store the bound change as pending bound change
10146  */
10147  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10148  {
10149  assert(tree != NULL);
10150  assert(transprob != NULL);
10151  assert(SCIPprobIsTransformed(transprob));
10152 
10153  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10154  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10155  }
10156  else
10157  {
10158  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10159  }
10160 
10161  if( nbdchgs != NULL )
10162  (*nbdchgs)++;
10163  }
10164  }
10165  else if( SCIPvarIsActive(vubvar) )
10166  {
10167  SCIP_Real xlb;
10168  SCIP_Real xub;
10169  SCIP_Real zlb;
10170  SCIP_Real zub;
10171  SCIP_Real minvub;
10172  SCIP_Real maxvub;
10173 
10175  assert(vubcoef != 0.0);
10176 
10177  minvub = -SCIPsetInfinity(set);
10178  maxvub = SCIPsetInfinity(set);
10179 
10180  xlb = SCIPvarGetLbGlobal(var);
10181  xub = SCIPvarGetUbGlobal(var);
10182  zlb = SCIPvarGetLbGlobal(vubvar);
10183  zub = SCIPvarGetUbGlobal(vubvar);
10184 
10185  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10186  if( vubcoef >= 0.0 )
10187  {
10188  SCIP_Real newzlb;
10189 
10190  if( !SCIPsetIsInfinity(set, -xlb) )
10191  {
10192  /* x <= b*z + d -> z >= (x-d)/b */
10193  newzlb = (xlb - vubconstant)/vubcoef;
10194  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10195  {
10196  *infeasible = TRUE;
10197  return SCIP_OKAY;
10198  }
10199  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10200  {
10201  /* bound might be adjusted due to integrality condition */
10202  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10203 
10204  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10205  * with the local bound, in this case we need to store the bound change as pending bound change
10206  */
10207  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10208  {
10209  assert(tree != NULL);
10210  assert(transprob != NULL);
10211  assert(SCIPprobIsTransformed(transprob));
10212 
10213  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10214  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10215  }
10216  else
10217  {
10218  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10219  }
10220  zlb = newzlb;
10221 
10222  if( nbdchgs != NULL )
10223  (*nbdchgs)++;
10224  }
10225  minvub = vubcoef * zlb + vubconstant;
10226  if( !SCIPsetIsInfinity(set, zub) )
10227  maxvub = vubcoef * zub + vubconstant;
10228  }
10229  else
10230  {
10231  if( !SCIPsetIsInfinity(set, zub) )
10232  maxvub = vubcoef * zub + vubconstant;
10233  if( !SCIPsetIsInfinity(set, -zlb) )
10234  minvub = vubcoef * zlb + vubconstant;
10235  }
10236  }
10237  else
10238  {
10239  SCIP_Real newzub;
10240 
10241  if( !SCIPsetIsInfinity(set, -xlb) )
10242  {
10243  /* x <= b*z + d -> z <= (x-d)/b */
10244  newzub = (xlb - vubconstant)/vubcoef;
10245  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10246  {
10247  *infeasible = TRUE;
10248  return SCIP_OKAY;
10249  }
10250  if( SCIPsetIsFeasLT(set, newzub, zub) )
10251  {
10252  /* bound might be adjusted due to integrality condition */
10253  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10254 
10255  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10256  * with the local bound, in this case we need to store the bound change as pending bound change
10257  */
10258  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10259  {
10260  assert(tree != NULL);
10261  assert(transprob != NULL);
10262  assert(SCIPprobIsTransformed(transprob));
10263 
10264  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10265  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10266  }
10267  else
10268  {
10269  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10270  }
10271  zub = newzub;
10272 
10273  if( nbdchgs != NULL )
10274  (*nbdchgs)++;
10275  }
10276  minvub = vubcoef * zub + vubconstant;
10277  if( !SCIPsetIsInfinity(set, -zlb) )
10278  maxvub = vubcoef * zlb + vubconstant;
10279  }
10280  else
10281  {
10282  if( !SCIPsetIsInfinity(set, zub) )
10283  minvub = vubcoef * zub + vubconstant;
10284  if( !SCIPsetIsInfinity(set, -zlb) )
10285  maxvub = vubcoef * zlb + vubconstant;
10286  }
10287  }
10288  if( minvub > maxvub )
10289  minvub = maxvub;
10290 
10291  /* adjust bounds due to integrality of vub variable */
10292  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10293  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10294 
10295  /* check bounds for feasibility */
10296  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10297  {
10298  *infeasible = TRUE;
10299  return SCIP_OKAY;
10300  }
10301 
10302  /* improve global upper bound of variable */
10303  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10304  {
10305  /* bound might be adjusted due to integrality condition */
10306  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10307 
10308  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10309  * with the local bound, in this case we need to store the bound change as pending bound change
10310  */
10311  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10312  {
10313  assert(tree != NULL);
10314  assert(transprob != NULL);
10315  assert(SCIPprobIsTransformed(transprob));
10316 
10317  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10318  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10319  }
10320  else
10321  {
10322  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10323  }
10324  xub = maxvub;
10325 
10326  if( nbdchgs != NULL )
10327  (*nbdchgs)++;
10328  }
10329  maxvub = xub;
10330 
10331  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10332  if( SCIPvarIsBinary(vubvar) )
10333  {
10334  /* b > 0: x <= (maxvub - minvub) * z + minvub
10335  * b < 0: x <= (minvub - maxvub) * z + maxvub
10336  */
10337 
10338  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10339 
10340  if( vubcoef >= 0.0 )
10341  {
10342  vubcoef = maxvub - minvub;
10343  vubconstant = minvub;
10344  }
10345  else
10346  {
10347  vubcoef = minvub - maxvub;
10348  vubconstant = maxvub;
10349  }
10350  }
10351 
10352  /* add variable bound to the variable bounds list */
10353  if( SCIPsetIsFeasLT(set, minvub, xub) )
10354  {
10355  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10356  assert(!SCIPsetIsZero(set, vubcoef));
10357 
10358  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10359  * list, thereby also adding the variable bound (or implication) to the other variable
10360  */
10361  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10362  {
10363  /* add corresponding implication:
10364  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10365  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10366  */
10367  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10368  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10369  infeasible, nbdchgs) );
10370  }
10371  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10372  {
10373  /* add corresponding implication:
10374  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10375  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10376  */
10377  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10378  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10379  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10380  }
10381  else
10382  {
10383  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10384  }
10385  }
10386  }
10387  break;
10388 
10390  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10391  * y >= b/a * z + (d-c)/a, if a < 0
10392  */
10393  assert(var->data.aggregate.var != NULL);
10394  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10395  {
10396  /* a > 0 -> add variable upper bound */
10397  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10398  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10399  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10400  }
10401  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10402  {
10403  /* a < 0 -> add variable lower bound */
10404  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10405  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10406  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10407  }
10408  else
10409  {
10410  SCIPerrorMessage("scalar is zero in aggregation\n");
10411  return SCIP_INVALIDDATA;
10412  }
10413  break;
10414 
10416  /* nothing to do here */
10417  break;
10418 
10420  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10421  assert(var->negatedvar != NULL);
10423  assert(var->negatedvar->negatedvar == var);
10424  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10425  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10426  nbdchgs) );
10427  break;
10428 
10429  default:
10430  SCIPerrorMessage("unknown variable status\n");
10431  return SCIP_INVALIDDATA;
10432  }
10433 
10434  return SCIP_OKAY;
10435 }
10436 
10437 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10438  * also adds the corresponding implication or variable bound to the implied variable;
10439  * if the implication is conflicting, the variable is fixed to the opposite value;
10440  * if the variable is already fixed to the given value, the implication is performed immediately;
10441  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10442  */
10444  SCIP_VAR* var, /**< problem variable */
10445  BMS_BLKMEM* blkmem, /**< block memory */
10446  SCIP_SET* set, /**< global SCIP settings */
10447  SCIP_STAT* stat, /**< problem statistics */
10448  SCIP_PROB* transprob, /**< transformed problem */
10449  SCIP_PROB* origprob, /**< original problem */
10450  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10451  SCIP_REOPT* reopt, /**< reoptimization data structure */
10452  SCIP_LP* lp, /**< current LP data */
10453  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10454  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10455  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10456  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10457  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10458  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10459  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10460  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10461  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10462  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10463  )
10464 {
10465  assert(var != NULL);
10466  assert(set != NULL);
10467  assert(var->scip == set->scip);
10468  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10469  assert(infeasible != NULL);
10470 
10471  *infeasible = FALSE;
10472  if( nbdchgs != NULL )
10473  *nbdchgs = 0;
10474 
10475  switch( SCIPvarGetStatus(var) )
10476  {
10478  assert(var->data.original.transvar != NULL);
10479  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10480  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10481  nbdchgs) );
10482  break;
10483 
10484  case SCIP_VARSTATUS_COLUMN:
10485  case SCIP_VARSTATUS_LOOSE:
10486  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10487  * the variable, the implication can be applied directly;
10488  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10489  */
10490  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10491  {
10492  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10493  {
10494  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10495  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10496  }
10497  }
10498  else
10499  {
10500  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10501  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10502  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10503  {
10504  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10505  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10506  }
10507  }
10508  break;
10509 
10510  case SCIP_VARSTATUS_FIXED:
10511  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10512  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10513  {
10514  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10515  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10516  }
10517  break;
10518 
10520  /* implication added for x == 1:
10521  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10522  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10523  * implication added for x == 0:
10524  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10525  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10526  *
10527  * use only binary variables z
10528  */
10529  assert(var->data.aggregate.var != NULL);
10530  if( SCIPvarIsBinary(var->data.aggregate.var) )
10531  {
10532  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10533  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10534 
10535  if( var->data.aggregate.scalar > 0 )
10536  {
10537  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10538  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10539  nbdchgs) );
10540  }
10541  else
10542  {
10543  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10544  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10545  nbdchgs) );
10546  }
10547  }
10548  break;
10549 
10551  /* nothing to do here */
10552  break;
10553 
10555  /* implication added for x == 1:
10556  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10557  * implication added for x == 0:
10558  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10559  */
10560  assert(var->negatedvar != NULL);
10562  assert(var->negatedvar->negatedvar == var);
10563  assert(SCIPvarIsBinary(var->negatedvar));
10564 
10566  {
10567  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10568  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10569  }
10570  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10571  else
10572  {
10573  /* if the implied variable is of binary type exchange the variables */
10574  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10575  {
10576  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10577  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10578  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10579  infeasible, nbdchgs) );
10580  }
10581  else
10582  {
10583  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10584  * implication as variable bounds
10585  */
10586 
10587  /* add variable lower bound on the negation of var */
10588  if( varfixing )
10589  {
10590  /* (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
10591  * as variable lower bound
10592  */
10593  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10594  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10595  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10596  }
10597  else
10598  {
10599  /* (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
10600  * as variable upper bound
10601  */
10602  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10603  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10604  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10605  }
10606 
10607  /* add variable bound on implvar */
10608  if( impltype == SCIP_BOUNDTYPE_UPPER )
10609  {
10610  /* (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
10611  * as variable upper bound
10612  */
10613  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10614  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10615  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10616  }
10617  else
10618  {
10619  /* (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
10620  * as variable upper bound
10621  */
10622  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10623  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10624  transitive, infeasible, nbdchgs) );
10625  }
10626  }
10627  }
10628  break;
10629 
10630  default:
10631  SCIPerrorMessage("unknown variable status\n");
10632  return SCIP_INVALIDDATA;
10633  }
10634 
10635  return SCIP_OKAY;
10636 }
10637 
10638 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10639  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10640  * both variables must be active, variable x must be binary
10641  */
10643  SCIP_VAR* var, /**< problem variable x */
10644  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10645  SCIP_VAR* implvar, /**< variable y to search for */
10646  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10647  )
10648 {
10649  assert(var != NULL);
10650  assert(implvar != NULL);
10651  assert(SCIPvarIsActive(var));
10652  assert(SCIPvarIsActive(implvar));
10653  assert(SCIPvarIsBinary(var));
10654 
10655  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10656 }
10657 
10658 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10659  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10660  * both variables must be active binary variables
10661  */
10663  SCIP_VAR* var, /**< problem variable x */
10664  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10665  SCIP_VAR* implvar, /**< variable y to search for */
10666  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10667  )
10668 {
10669  assert(SCIPvarIsBinary(implvar));
10670 
10671  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10672 }
10673 
10674 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10676  SCIP_VAR* var, /**< problem variable */
10677  BMS_BLKMEM* blkmem, /**< block memory */
10678  SCIP_SET* set, /**< global SCIP settings */
10679  SCIP_STAT* stat, /**< problem statistics */
10680  SCIP_PROB* transprob, /**< transformed problem */
10681  SCIP_PROB* origprob, /**< original problem */
10682  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10683  SCIP_REOPT* reopt, /**< reoptimization data structure */
10684  SCIP_LP* lp, /**< current LP data */
10685  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10686  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10687  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10688  SCIP_Bool value, /**< value to fix variable to */
10689  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10690  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10691  )
10692 {
10693  assert(var != NULL);
10694  assert(set != NULL);
10695  assert(var->scip == set->scip);
10696  assert(infeasible != NULL);
10697 
10698  *infeasible = FALSE;
10699 
10700  if( value == FALSE )
10701  {
10702  if( var->glbdom.lb > 0.5 )
10703  *infeasible = TRUE;
10704  else if( var->glbdom.ub > 0.5 )
10705  {
10706  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10707  * with the local bound, in this case we need to store the bound change as pending bound change
10708  */
10709  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10710  {
10711  assert(tree != NULL);
10712  assert(transprob != NULL);
10713  assert(SCIPprobIsTransformed(transprob));
10714 
10715  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10716  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10717  }
10718  else
10719  {
10720  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10721  }
10722 
10723  if( nbdchgs != NULL )
10724  (*nbdchgs)++;
10725  }
10726  }
10727  else
10728  {
10729  if( var->glbdom.ub < 0.5 )
10730  *infeasible = TRUE;
10731  else if( var->glbdom.lb < 0.5 )
10732  {
10733  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10734  * with the local bound, in this case we need to store the bound change as pending bound change
10735  */
10736  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10737  {
10738  assert(tree != NULL);
10739  assert(transprob != NULL);
10740  assert(SCIPprobIsTransformed(transprob));
10741 
10742  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10743  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10744  }
10745  else
10746  {
10747  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10748  }
10749 
10750  if( nbdchgs != NULL )
10751  (*nbdchgs)++;
10752  }
10753  }
10754 
10755  /* during presolving, the variable should have been removed immediately from all its cliques */
10756  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10757 
10758  return SCIP_OKAY;
10759 }
10760 
10761 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10762  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10763  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10764  * the opposite of the value they take in the clique
10765  */
10767  SCIP_VAR* var, /**< problem variable */
10768  BMS_BLKMEM* blkmem, /**< block memory */
10769  SCIP_SET* set, /**< global SCIP settings */
10770  SCIP_STAT* stat, /**< problem statistics */
10771  SCIP_PROB* transprob, /**< transformed problem */
10772  SCIP_PROB* origprob, /**< original problem */
10773  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10774  SCIP_REOPT* reopt, /**< reoptimization data structure */
10775  SCIP_LP* lp, /**< current LP data */
10776  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10777  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10778  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10779  SCIP_Bool value, /**< value of the variable in the clique */
10780  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10781  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10782  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10783  )
10784 {
10785  assert(var != NULL);
10786  assert(set != NULL);
10787  assert(var->scip == set->scip);
10788  assert(SCIPvarIsBinary(var));
10789  assert(infeasible != NULL);
10790 
10791  *infeasible = FALSE;
10792 
10793  /* get corresponding active problem variable */
10794  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10799  assert(SCIPvarIsBinary(var));
10800 
10801  /* only column and loose variables may be member of a clique */
10803  {
10804  SCIP_Bool doubleentry;
10805  SCIP_Bool oppositeentry;
10806 
10807  /* add variable to clique */
10808  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10809 
10810  /* add clique to variable's clique list */
10811  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10812 
10813  /* check consistency of cliquelist */
10814  SCIPcliquelistCheck(var->cliquelist, var);
10815 
10816  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10817  if( doubleentry )
10818  {
10819  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10820  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10821  }
10822 
10823  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10824  * to the opposite of the value they take in the clique
10825  */
10826  if( oppositeentry )
10827  {
10828  SCIP_VAR** vars;
10829  SCIP_Bool* values;
10830  int nvars;
10831  int i;
10832 
10833  nvars = SCIPcliqueGetNVars(clique);
10834  vars = SCIPcliqueGetVars(clique);
10835  values = SCIPcliqueGetValues(clique);
10836  for( i = 0; i < nvars && !(*infeasible); ++i )
10837  {
10838  if( vars[i] == var )
10839  continue;
10840 
10841  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10842  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10843  }
10844  }
10845  }
10846 
10847  return SCIP_OKAY;
10848 }
10849 
10850 /** adds a filled clique to the cliquelists of all corresponding variables */
10852  SCIP_VAR** vars, /**< problem variables */
10853  SCIP_Bool* values, /**< values of the variables in the clique */
10854  int nvars, /**< number of problem variables */
10855  BMS_BLKMEM* blkmem, /**< block memory */
10856  SCIP_SET* set, /**< global SCIP settings */
10857  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10858  )
10859 {
10860  SCIP_VAR* var;
10861  int v;
10862 
10863  assert(vars != NULL);
10864  assert(values != NULL);
10865  assert(nvars > 0);
10866  assert(set != NULL);
10867  assert(blkmem != NULL);
10868  assert(clique != NULL);
10869 
10870  for( v = nvars - 1; v >= 0; --v )
10871  {
10872  var = vars[v];
10873  assert(SCIPvarIsBinary(var));
10875 
10876  /* add clique to variable's clique list */
10877  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10878 
10879  /* check consistency of cliquelist */
10880  SCIPcliquelistCheck(var->cliquelist, var);
10881  }
10882 
10883  return SCIP_OKAY;
10884 }
10885 
10886 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10887  * itself
10888  */
10890  SCIP_VAR* var, /**< problem variable */
10891  BMS_BLKMEM* blkmem, /**< block memory */
10892  SCIP_SET* set, /**< global SCIP settings */
10893  SCIP_Bool value, /**< value of the variable in the clique */
10894  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10895  )
10896 {
10897  assert(var != NULL);
10898  assert(SCIPvarIsBinary(var));
10900 
10901  /* add clique to variable's clique list */
10902  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10903 
10904  return SCIP_OKAY;
10905 }
10906 
10907 
10908 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10909  * itself
10910  */
10912  SCIP_VAR* var, /**< problem variable */
10913  BMS_BLKMEM* blkmem, /**< block memory */
10914  SCIP_Bool value, /**< value of the variable in the clique */
10915  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10916  )
10917 {
10918  assert(var != NULL);
10919  assert(SCIPvarIsBinary(var));
10920 
10921  /* delete clique from variable's clique list */
10922  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10923 
10924  return SCIP_OKAY;
10925 }
10926 
10927 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10929  SCIP_VAR* var, /**< problem variable */
10930  BMS_BLKMEM* blkmem, /**< block memory */
10931  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10932  SCIP_Bool value, /**< value of the variable in the clique */
10933  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10934  )
10935 {
10936  assert(var != NULL);
10937  assert(SCIPvarIsBinary(var));
10938 
10939  /* get corresponding active problem variable */
10940  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10945  assert(SCIPvarIsBinary(var));
10946 
10947  /* only column and loose variables may be member of a clique */
10949  {
10950  /* delete clique from variable's clique list */
10951  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10952 
10953  /* delete variable from clique */
10954  SCIPcliqueDelVar(clique, cliquetable, var, value);
10955 
10956  /* check consistency of cliquelist */
10957  SCIPcliquelistCheck(var->cliquelist, var);
10958  }
10959 
10960  return SCIP_OKAY;
10961 }
10962 
10963 /** returns whether there is a clique that contains both given variable/value pairs;
10964  * the variables must be active binary variables;
10965  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10966  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10967  *
10968  * @note a variable with it's negated variable are NOT! in a clique
10969  * @note a variable with itself are in a clique
10970  */
10972  SCIP_VAR* var1, /**< first variable */
10973  SCIP_Bool value1, /**< value of first variable */
10974  SCIP_VAR* var2, /**< second variable */
10975  SCIP_Bool value2, /**< value of second variable */
10976  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10977  )
10978 {
10979  assert(var1 != NULL);
10980  assert(var2 != NULL);
10981  assert(SCIPvarIsActive(var1));
10982  assert(SCIPvarIsActive(var2));
10983  assert(SCIPvarIsBinary(var1));
10984  assert(SCIPvarIsBinary(var2));
10985 
10986  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10987  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10988 }
10989 
10990 /** actually changes the branch factor of the variable and of all parent variables */
10991 static
10993  SCIP_VAR* var, /**< problem variable */
10994  SCIP_SET* set, /**< global SCIP settings */
10995  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10996  )
10997 {
10998  SCIP_VAR* parentvar;
10999  SCIP_Real eps;
11000  int i;
11001 
11002  assert(var != NULL);
11003  assert(set != NULL);
11004  assert(var->scip == set->scip);
11005 
11006  /* only use positive values */
11007  eps = SCIPsetEpsilon(set);
11008  branchfactor = MAX(branchfactor, eps);
11009 
11010  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11011 
11012  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11013  return SCIP_OKAY;
11014 
11015  /* change the branch factor */
11016  var->branchfactor = branchfactor;
11017 
11018  /* process parent variables */
11019  for( i = 0; i < var->nparentvars; ++i )
11020  {
11021  parentvar = var->parentvars[i];
11022  assert(parentvar != NULL);
11023 
11024  switch( SCIPvarGetStatus(parentvar) )
11025  {
11027  /* do not change priorities across the border between transformed and original problem */
11028  break;
11029 
11030  case SCIP_VARSTATUS_COLUMN:
11031  case SCIP_VARSTATUS_LOOSE:
11032  case SCIP_VARSTATUS_FIXED:
11034  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11035  SCIPABORT();
11036  return SCIP_INVALIDDATA; /*lint !e527*/
11037 
11040  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11041  break;
11042 
11043  default:
11044  SCIPerrorMessage("unknown variable status\n");
11045  SCIPABORT();
11046  return SCIP_ERROR; /*lint !e527*/
11047  }
11048  }
11049 
11050  return SCIP_OKAY;
11051 }
11052 
11053 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11054  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11055  */
11057  SCIP_VAR* var, /**< problem variable */
11058  SCIP_SET* set, /**< global SCIP settings */
11059  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11060  )
11061 {
11062  int v;
11063 
11064  assert(var != NULL);
11065  assert(set != NULL);
11066  assert(var->scip == set->scip);
11067  assert(branchfactor >= 0.0);
11068 
11069  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11070 
11071  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11072  return SCIP_OKAY;
11073 
11074  /* change priorities of attached variables */
11075  switch( SCIPvarGetStatus(var) )
11076  {
11078  if( var->data.original.transvar != NULL )
11079  {
11080  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11081  }
11082  else
11083  {
11084  assert(set->stage == SCIP_STAGE_PROBLEM);
11085  var->branchfactor = branchfactor;
11086  }
11087  break;
11088 
11089  case SCIP_VARSTATUS_COLUMN:
11090  case SCIP_VARSTATUS_LOOSE:
11091  case SCIP_VARSTATUS_FIXED:
11092  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11093  break;
11094 
11096  assert(var->data.aggregate.var != NULL);
11097  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11098  break;
11099 
11101  assert(!var->donotmultaggr);
11102  for( v = 0; v < var->data.multaggr.nvars; ++v )
11103  {
11104  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11105  }
11106  break;
11107 
11109  assert(var->negatedvar != NULL);
11111  assert(var->negatedvar->negatedvar == var);
11112  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11113  break;
11114 
11115  default:
11116  SCIPerrorMessage("unknown variable status\n");
11117  SCIPABORT();
11118  return SCIP_ERROR; /*lint !e527*/
11119  }
11120 
11121  return SCIP_OKAY;
11122 }
11123 
11124 /** actually changes the branch priority of the variable and of all parent variables */
11125 static
11127  SCIP_VAR* var, /**< problem variable */
11128  int branchpriority /**< branching priority of the variable */
11129  )
11130 {
11131  SCIP_VAR* parentvar;
11132  int i;
11133 
11134  assert(var != NULL);
11135 
11136  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11137  var->name, var->branchpriority, branchpriority);
11138 
11139  if( branchpriority == var->branchpriority )
11140  return SCIP_OKAY;
11141 
11142  /* change the branch priority */
11143  var->branchpriority = branchpriority;
11144 
11145  /* process parent variables */
11146  for( i = 0; i < var->nparentvars; ++i )
11147  {
11148  parentvar = var->parentvars[i];
11149  assert(parentvar != NULL);
11150 
11151  switch( SCIPvarGetStatus(parentvar) )
11152  {
11154  /* do not change priorities across the border between transformed and original problem */
11155  break;
11156 
11157  case SCIP_VARSTATUS_COLUMN:
11158  case SCIP_VARSTATUS_LOOSE:
11159  case SCIP_VARSTATUS_FIXED:
11161  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11162  SCIPABORT();
11163  return SCIP_INVALIDDATA; /*lint !e527*/
11164 
11167  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11168  break;
11169 
11170  default:
11171  SCIPerrorMessage("unknown variable status\n");
11172  return SCIP_ERROR;
11173  }
11174  }
11175 
11176  return SCIP_OKAY;
11177 }
11178 
11179 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11180  * with lower priority in selection of branching variable
11181  */
11183  SCIP_VAR* var, /**< problem variable */
11184  int branchpriority /**< branching priority of the variable */
11185  )
11186 {
11187  int v;
11188 
11189  assert(var != NULL);
11190 
11191  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11192 
11193  if( var->branchpriority == branchpriority )
11194  return SCIP_OKAY;
11195 
11196  /* change priorities of attached variables */
11197  switch( SCIPvarGetStatus(var) )
11198  {
11200  if( var->data.original.transvar != NULL )
11201  {
11202  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11203  }
11204  else
11205  var->branchpriority = branchpriority;
11206  break;
11207 
11208  case SCIP_VARSTATUS_COLUMN:
11209  case SCIP_VARSTATUS_LOOSE:
11210  case SCIP_VARSTATUS_FIXED:
11211  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11212  break;
11213 
11215  assert(var->data.aggregate.var != NULL);
11216  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11217  break;
11218 
11220  assert(!var->donotmultaggr);
11221  for( v = 0; v < var->data.multaggr.nvars; ++v )
11222  {
11223  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11224  }
11225  break;
11226 
11228  assert(var->negatedvar != NULL);
11230  assert(var->negatedvar->negatedvar == var);
11231  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11232  break;
11233 
11234  default:
11235  SCIPerrorMessage("unknown variable status\n");
11236  SCIPABORT();
11237  return SCIP_ERROR; /*lint !e527*/
11238  }
11239 
11240  return SCIP_OKAY;
11241 }
11242 
11243 /** actually changes the branch direction of the variable and of all parent variables */
11244 static
11246  SCIP_VAR* var, /**< problem variable */
11247  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11248  )
11249 {
11250  SCIP_VAR* parentvar;
11251  int i;
11252 
11253  assert(var != NULL);
11254 
11255  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11256  var->name, var->branchdirection, branchdirection);
11257 
11258  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11259  return SCIP_OKAY;
11260 
11261  /* change the branch direction */
11262  var->branchdirection = branchdirection; /*lint !e641*/
11263 
11264  /* process parent variables */
11265  for( i = 0; i < var->nparentvars; ++i )
11266  {
11267  parentvar = var->parentvars[i];
11268  assert(parentvar != NULL);
11269 
11270  switch( SCIPvarGetStatus(parentvar) )
11271  {
11273  /* do not change directions across the border between transformed and original problem */
11274  break;
11275 
11276  case SCIP_VARSTATUS_COLUMN:
11277  case SCIP_VARSTATUS_LOOSE:
11278  case SCIP_VARSTATUS_FIXED:
11280  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11281  SCIPABORT();
11282  return SCIP_INVALIDDATA; /*lint !e527*/
11283 
11285  if( parentvar->data.aggregate.scalar > 0.0 )
11286  {
11287  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11288  }
11289  else
11290  {
11291  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11292  }
11293  break;
11294 
11296  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11297  break;
11298 
11299  default:
11300  SCIPerrorMessage("unknown variable status\n");
11301  SCIPABORT();
11302  return SCIP_ERROR; /*lint !e527*/
11303  }
11304  }
11305 
11306  return SCIP_OKAY;
11307 }
11308 
11309 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11310  * with lower direction in selection of branching variable
11311  */
11313  SCIP_VAR* var, /**< problem variable */
11314  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11315  )
11316 {
11317  int v;
11318 
11319  assert(var != NULL);
11320 
11321  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11322 
11323  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11324  return SCIP_OKAY;
11325 
11326  /* change directions of attached variables */
11327  switch( SCIPvarGetStatus(var) )
11328  {
11330  if( var->data.original.transvar != NULL )
11331  {
11332  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11333  }
11334  else
11335  var->branchdirection = branchdirection; /*lint !e641*/
11336  break;
11337 
11338  case SCIP_VARSTATUS_COLUMN:
11339  case SCIP_VARSTATUS_LOOSE:
11340  case SCIP_VARSTATUS_FIXED:
11341  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11342  break;
11343 
11345  assert(var->data.aggregate.var != NULL);
11346  if( var->data.aggregate.scalar > 0.0 )
11347  {
11348  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11349  }
11350  else
11351  {
11353  }
11354  break;
11355 
11357  assert(!var->donotmultaggr);
11358  for( v = 0; v < var->data.multaggr.nvars; ++v )
11359  {
11360  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11361  assert(var->data.multaggr.vars[v] != NULL);
11363  {
11364  if( var->data.multaggr.scalars[v] > 0.0 )
11365  {
11366  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11367  }
11368  else
11369  {
11371  }
11372  }
11373  }
11374  break;
11375 
11377  assert(var->negatedvar != NULL);
11379  assert(var->negatedvar->negatedvar == var);
11381  break;
11382 
11383  default:
11384  SCIPerrorMessage("unknown variable status\n");
11385  SCIPABORT();
11386  return SCIP_ERROR; /*lint !e527*/
11387  }
11388 
11389  return SCIP_OKAY;
11390 }
11391 
11392 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11393  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11394  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11395  * are equal, which means both variables are equal
11396  */
11398  SCIP_VAR* var1, /**< first problem variable */
11399  SCIP_VAR* var2 /**< second problem variable */
11400  )
11401 {
11402  assert(var1 != NULL);
11403  assert(var2 != NULL);
11406 
11408  var1 = SCIPvarGetNegatedVar(var1);
11410  var2 = SCIPvarGetNegatedVar(var2);
11411 
11412  assert(var1 != NULL);
11413  assert(var2 != NULL);
11414 
11415  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11416  return -1;
11417  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11418  return +1;
11419 
11420  assert(var1 == var2);
11421  return 0;
11422 }
11423 
11424 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11425  * variables are handled as the same variables
11426  */
11427 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11429  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11430 }
11431 
11432 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11433  * variable index; returns 0 if both indices are equal, which means both variables are equal
11434  */
11435 int SCIPvarCompare(
11436  SCIP_VAR* var1, /**< first problem variable */
11437  SCIP_VAR* var2 /**< second problem variable */
11438  )
11439 {
11440  assert(var1 != NULL);
11441  assert(var2 != NULL);
11442 
11443  if( var1->index < var2->index )
11444  return -1;
11445  else if( var1->index > var2->index )
11446  return +1;
11447  else
11448  {
11449  assert(var1 == var2);
11450  return 0;
11451  }
11452 }
11453 
11454 /** comparison method for sorting variables by non-decreasing index */
11455 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11457  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11458 }
11459 
11460 /** comparison method for sorting variables by non-decreasing objective coefficient */
11461 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11463  SCIP_Real obj1;
11464  SCIP_Real obj2;
11465 
11466  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11467  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11468 
11469  if( obj1 < obj2 )
11470  return -1;
11471  else if( obj1 > obj2 )
11472  return +1;
11473  else
11474  return 0;
11475 }
11476 
11477 /** hash key retrieval function for variables */
11478 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11479 { /*lint --e{715}*/
11480  return elem;
11481 }
11482 
11483 /** returns TRUE iff the indices of both variables are equal */
11484 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11485 { /*lint --e{715}*/
11486  if( key1 == key2 )
11487  return TRUE;
11488  return FALSE;
11489 }
11490 
11491 /** returns the hash value of the key */
11492 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11493 { /*lint --e{715}*/
11494  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11495  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11496 }
11497 
11498 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11500  SCIP_SET* set, /**< global SCIP settings */
11501  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11502  * variables, if enough slots exist
11503  */
11504  int* nvars, /**< number of given variables, and as output number of active variables,
11505  * if enough slots exist
11506  */
11507  int varssize, /**< available slots in vars array */
11508  int* requiredsize /**< pointer to store the required array size for the active variables */
11509  )
11510 {
11511  SCIP_VAR** activevars;
11512  int nactivevars;
11513  int activevarssize;
11514 
11515  SCIP_VAR* var;
11516  int v;
11517 
11518  SCIP_VAR** tmpvars;
11519  SCIP_VAR** multvars;
11520  int tmpvarssize;
11521  int ntmpvars;
11522  int noldtmpvars;
11523  int nmultvars;
11524 
11525  assert(set != NULL);
11526  assert(nvars != NULL);
11527  assert(vars != NULL || *nvars == 0);
11528  assert(varssize >= *nvars);
11529  assert(requiredsize != NULL);
11530 
11531  *requiredsize = 0;
11532 
11533  if( *nvars == 0 )
11534  return SCIP_OKAY;
11535 
11536  nactivevars = 0;
11537  activevarssize = *nvars;
11538  ntmpvars = *nvars;
11539  tmpvarssize = *nvars;
11540 
11541  /* temporary memory */
11542  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11543  /* coverity[copy_paste_error] */
11544  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11545 
11546  noldtmpvars = ntmpvars;
11547 
11548  /* sort all variables to combine equal variables easily */
11549  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11550  for( v = ntmpvars - 1; v > 0; --v )
11551  {
11552  /* combine same variables */
11553  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11554  {
11555  --ntmpvars;
11556  tmpvars[v] = tmpvars[ntmpvars];
11557  }
11558  }
11559  /* sort all variables again to combine equal variables later on */
11560  if( noldtmpvars > ntmpvars )
11561  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11562 
11563  /* collect for each variable the representation in active variables */
11564  while( ntmpvars >= 1 )
11565  {
11566  --ntmpvars;
11567  var = tmpvars[ntmpvars];
11568  assert( var != NULL );
11569 
11570  switch( SCIPvarGetStatus(var) )
11571  {
11573  if( var->data.original.transvar == NULL )
11574  {
11575  SCIPerrorMessage("original variable has no transformed variable attached\n");
11576  SCIPABORT();
11577  return SCIP_INVALIDDATA; /*lint !e527*/
11578  }
11579  tmpvars[ntmpvars] = var->data.original.transvar;
11580  ++ntmpvars;
11581  break;
11582 
11584  tmpvars[ntmpvars] = var->data.aggregate.var;
11585  ++ntmpvars;
11586  break;
11587 
11589  tmpvars[ntmpvars] = var->negatedvar;
11590  ++ntmpvars;
11591  break;
11592 
11593  case SCIP_VARSTATUS_LOOSE:
11594  case SCIP_VARSTATUS_COLUMN:
11595  /* check for space in temporary memory */
11596  if( nactivevars >= activevarssize )
11597  {
11598  activevarssize *= 2;
11599  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11600  assert(nactivevars < activevarssize);
11601  }
11602  activevars[nactivevars] = var;
11603  nactivevars++;
11604  break;
11605 
11607  /* x = a_1*y_1 + ... + a_n*y_n + c */
11608  nmultvars = var->data.multaggr.nvars;
11609  multvars = var->data.multaggr.vars;
11610 
11611  /* check for space in temporary memory */
11612  if( nmultvars + ntmpvars > tmpvarssize )
11613  {
11614  while( nmultvars + ntmpvars > tmpvarssize )
11615  tmpvarssize *= 2;
11616  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11617  assert(nmultvars + ntmpvars <= tmpvarssize);
11618  }
11619 
11620  /* copy all multi-aggregation variables into our working array */
11621  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11622 
11623  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11624  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11625 
11626  ntmpvars += nmultvars;
11627  noldtmpvars = ntmpvars;
11628 
11629  /* sort all variables to combine equal variables easily */
11630  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11631  for( v = ntmpvars - 1; v > 0; --v )
11632  {
11633  /* combine same variables */
11634  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11635  {
11636  --ntmpvars;
11637  tmpvars[v] = tmpvars[ntmpvars];
11638  }
11639  }
11640  /* sort all variables again to combine equal variables later on */
11641  if( noldtmpvars > ntmpvars )
11642  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11643 
11644  break;
11645 
11646  case SCIP_VARSTATUS_FIXED:
11647  /* no need for memorizing fixed variables */
11648  break;
11649 
11650  default:
11651  SCIPerrorMessage("unknown variable status\n");
11652  SCIPABORT();
11653  return SCIP_INVALIDDATA; /*lint !e527*/
11654  }
11655  }
11656 
11657  /* sort variable array by variable index */
11658  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11659 
11660  /* eliminate duplicates and count required size */
11661  v = nactivevars - 1;
11662  while( v > 0 )
11663  {
11664  /* combine both variable since they are the same */
11665  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11666  {
11667  --nactivevars;
11668  activevars[v] = activevars[nactivevars];
11669  }
11670  --v;
11671  }
11672  *requiredsize = nactivevars;
11673 
11674  if( varssize >= *requiredsize )
11675  {
11676  assert(vars != NULL);
11677 
11678  *nvars = *requiredsize;
11679  BMScopyMemoryArray(vars, activevars, nactivevars);
11680  }
11681 
11682  SCIPsetFreeBufferArray(set, &tmpvars);
11683  SCIPsetFreeBufferArray(set, &activevars);
11684 
11685  return SCIP_OKAY;
11686 }
11687 
11688 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11689  * @note the content of the given array will/might change
11690  */
11691 void SCIPvarsGetProbvar(
11692  SCIP_VAR** vars, /**< array of problem variables */
11693  int nvars /**< number of variables */
11694  )
11695 {
11696  int v;
11697 
11698  assert(vars != NULL || nvars == 0);
11699 
11700  for( v = nvars - 1; v >= 0; --v )
11701  {
11702  assert(vars != NULL);
11703  assert(vars[v] != NULL);
11704 
11705  vars[v] = SCIPvarGetProbvar(vars[v]);
11706  assert(vars[v] != NULL);
11707  }
11708 }
11709 
11710 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11712  SCIP_VAR* var /**< problem variable */
11713  )
11714 {
11715  SCIP_VAR* retvar;
11716 
11717  assert(var != NULL);
11718 
11719  retvar = var;
11720 
11721  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11722 
11723  while( TRUE ) /*lint !e716 */
11724  {
11725  assert(retvar != NULL);
11726 
11727  switch( SCIPvarGetStatus(retvar) )
11728  {
11730  if( retvar->data.original.transvar == NULL )
11731  {
11732  SCIPerrorMessage("original variable has no transformed variable attached\n");
11733  SCIPABORT();
11734  return NULL; /*lint !e527 */
11735  }
11736  retvar = retvar->data.original.transvar;
11737  break;
11738 
11739  case SCIP_VARSTATUS_LOOSE:
11740  case SCIP_VARSTATUS_COLUMN:
11741  case SCIP_VARSTATUS_FIXED:
11742  return retvar;
11743 
11745  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11746  if ( retvar->data.multaggr.nvars == 1 )
11747  retvar = retvar->data.multaggr.vars[0];
11748  else
11749  return retvar;
11750  break;
11751 
11753  retvar = retvar->data.aggregate.var;
11754  break;
11755 
11757  retvar = retvar->negatedvar;
11758  break;
11759 
11760  default:
11761  SCIPerrorMessage("unknown variable status\n");
11762  SCIPABORT();
11763  return NULL; /*lint !e527*/
11764  }
11765  }
11766 }
11767 
11768 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11769  * negation status of each variable
11770  */
11772  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11773  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11774  int nvars /**< number of variables and values in vars and negated array */
11775  )
11776 {
11777  SCIP_VAR** var;
11778  SCIP_Bool* negated;
11779  int v;
11780 
11781  assert(vars != NULL);
11782  assert(*vars != NULL || nvars == 0);
11783  assert(negatedarr != NULL);
11784  assert(*negatedarr != NULL || nvars == 0);
11785 
11786  for( v = nvars - 1; v >= 0; --v )
11787  {
11788  var = &((*vars)[v]);
11789  negated = &((*negatedarr)[v]);
11790 
11791  /* get problem variable */
11792  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11793  }
11794 
11795  return SCIP_OKAY;
11796 }
11797 
11798 
11799 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11800  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11801  * FALSE is used)
11802  */
11804  SCIP_VAR** var, /**< pointer to binary problem variable */
11805  SCIP_Bool* negated /**< pointer to update the negation status */
11806  )
11807 {
11809 #ifndef NDEBUG
11810  SCIP_Real constant = 0.0;
11811  SCIP_Bool orignegated;
11812 #endif
11813 
11814  assert(var != NULL);
11815  assert(*var != NULL);
11816  assert(negated != NULL);
11817  assert(SCIPvarIsBinary(*var));
11818 
11819 #ifndef NDEBUG
11820  orignegated = *negated;
11821 #endif
11822 
11823  while( !active && *var != NULL )
11824  {
11825  switch( SCIPvarGetStatus(*var) )
11826  {
11828  if( (*var)->data.original.transvar == NULL )
11829  return SCIP_OKAY;
11830  *var = (*var)->data.original.transvar;
11831  break;
11832 
11833  case SCIP_VARSTATUS_LOOSE:
11834  case SCIP_VARSTATUS_COLUMN:
11835  case SCIP_VARSTATUS_FIXED:
11836  active = TRUE;
11837  break;
11838 
11840  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11841  if ( (*var)->data.multaggr.nvars == 1 )
11842  {
11843  assert( (*var)->data.multaggr.vars != NULL );
11844  assert( (*var)->data.multaggr.scalars != NULL );
11845  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11846  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11847 
11848  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11849  * another variable which needs to be fixed
11850  *
11851  * e.g. x = y - 1 => (x = 0 && y = 1)
11852  * e.g. x = y + 1 => (x = 1 && y = 0)
11853  *
11854  * is this special case we need to return the muti-aggregation
11855  */
11856  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)) )
11857  {
11858  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11859  }
11860  else
11861  {
11862  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11863  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11864  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11865  * we will return the aggregated variable;
11866  */
11867  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11868  {
11869  active = TRUE;
11870  break;
11871  }
11872 
11873  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11874  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11875  * so if this is the case, we will return the aggregated variable
11876  */
11877  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11878  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11879  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11880 
11881  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11882  {
11883  active = TRUE;
11884  break;
11885  }
11886 
11887  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11888 
11889  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11890  {
11891  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11892  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11893  * variable itself is multi-aggregated again?
11894  */
11895  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11896  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11897  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
11898  }
11899  else
11900  {
11901  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11902 #ifndef NDEBUG
11903  constant += (*negated) != orignegated ? -1.0 : 1.0;
11904 #endif
11905 
11906  *negated = !(*negated);
11907  }
11908  *var = (*var)->data.multaggr.vars[0];
11909  break;
11910  }
11911  }
11912  active = TRUE;
11913  break;
11914 
11915  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11916  assert((*var)->data.aggregate.var != NULL);
11917  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11918  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11919 #ifndef NDEBUG
11920  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11921 #endif
11922 
11923  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11924  *var = (*var)->data.aggregate.var;
11925  break;
11926 
11927  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11928  assert((*var)->negatedvar != NULL);
11929 #ifndef NDEBUG
11930  constant += (*negated) != orignegated ? -1.0 : 1.0;
11931 #endif
11932 
11933  *negated = !(*negated);
11934  *var = (*var)->negatedvar;
11935  break;
11936 
11937  default:
11938  SCIPerrorMessage("unknown variable status\n");
11939  return SCIP_INVALIDDATA;
11940  }
11941  }
11942  assert(active == (*var != NULL));
11943 
11944  if( active )
11945  {
11946  assert(SCIPvarIsBinary(*var));
11947  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11948  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11949 
11950  return SCIP_OKAY;
11951  }
11952  else
11953  {
11954  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11955  return SCIP_INVALIDDATA;
11956  }
11957 }
11958 
11959 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11960  * values
11961  */
11963  SCIP_VAR** var, /**< pointer to problem variable */
11964  SCIP_Real* bound, /**< pointer to bound value to transform */
11965  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11966  )
11967 {
11968  assert(var != NULL);
11969  assert(*var != NULL);
11970  assert(bound != NULL);
11971  assert(boundtype != NULL);
11972 
11973  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11974 
11975  switch( SCIPvarGetStatus(*var) )
11976  {
11978  if( (*var)->data.original.transvar == NULL )
11979  {
11980  SCIPerrorMessage("original variable has no transformed variable attached\n");
11981  return SCIP_INVALIDDATA;
11982  }
11983  *var = (*var)->data.original.transvar;
11984  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11985  break;
11986 
11987  case SCIP_VARSTATUS_LOOSE:
11988  case SCIP_VARSTATUS_COLUMN:
11989  case SCIP_VARSTATUS_FIXED:
11990  break;
11991 
11993  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11994  if ( (*var)->data.multaggr.nvars == 1 )
11995  {
11996  assert( (*var)->data.multaggr.vars != NULL );
11997  assert( (*var)->data.multaggr.scalars != NULL );
11998  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11999 
12000  (*bound) /= (*var)->data.multaggr.scalars[0];
12001  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12002  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12003  {
12004  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12005  *boundtype = SCIP_BOUNDTYPE_UPPER;
12006  else
12007  *boundtype = SCIP_BOUNDTYPE_LOWER;
12008  }
12009  *var = (*var)->data.multaggr.vars[0];
12010  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12011  }
12012  break;
12013 
12014  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12015  assert((*var)->data.aggregate.var != NULL);
12016  assert((*var)->data.aggregate.scalar != 0.0);
12017 
12018  (*bound) /= (*var)->data.aggregate.scalar;
12019  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12020  if( (*var)->data.aggregate.scalar < 0.0 )
12021  {
12022  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12023  *boundtype = SCIP_BOUNDTYPE_UPPER;
12024  else
12025  *boundtype = SCIP_BOUNDTYPE_LOWER;
12026  }
12027  *var = (*var)->data.aggregate.var;
12028  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12029  break;
12030 
12031  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12032  assert((*var)->negatedvar != NULL);
12033  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12034  assert((*var)->negatedvar->negatedvar == *var);
12035  (*bound) = (*var)->data.negate.constant - *bound;
12036  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12037  *boundtype = SCIP_BOUNDTYPE_UPPER;
12038  else
12039  *boundtype = SCIP_BOUNDTYPE_LOWER;
12040  *var = (*var)->negatedvar;
12041  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12042  break;
12043 
12044  default:
12045  SCIPerrorMessage("unknown variable status\n");
12046  return SCIP_INVALIDDATA;
12047  }
12048 
12049  return SCIP_OKAY;
12050 }
12051 
12052 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12053  * values
12054  */
12056  SCIP_VAR** var, /**< pointer to problem variable */
12057  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12058  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12059  )
12060 {
12061  assert(var != NULL);
12062  assert(*var != NULL);
12063  assert(left != NULL);
12064  assert(right != NULL);
12065 
12066  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12067 
12068  switch( SCIPvarGetStatus(*var) )
12069  {
12071  if( (*var)->data.original.transvar == NULL )
12072  {
12073  SCIPerrorMessage("original variable has no transformed variable attached\n");
12074  return SCIP_INVALIDDATA;
12075  }
12076  *var = (*var)->data.original.transvar;
12077  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12078  break;
12079 
12080  case SCIP_VARSTATUS_LOOSE:
12081  case SCIP_VARSTATUS_COLUMN:
12082  case SCIP_VARSTATUS_FIXED:
12084  break;
12085 
12086  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12087  assert((*var)->data.aggregate.var != NULL);
12088  assert((*var)->data.aggregate.scalar != 0.0);
12089 
12090  /* scale back */
12091  (*left) /= (*var)->data.aggregate.scalar;
12092  (*right) /= (*var)->data.aggregate.scalar;
12093 
12094  /* shift back */
12095  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12096  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12097 
12098  *var = (*var)->data.aggregate.var;
12099 
12100  /* check if the interval bounds have to swapped */
12101  if( (*var)->data.aggregate.scalar < 0.0 )
12102  {
12103  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12104  }
12105  else
12106  {
12107  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12108  }
12109  break;
12110 
12111  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12112  assert((*var)->negatedvar != NULL);
12113  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12114  assert((*var)->negatedvar->negatedvar == *var);
12115 
12116  /* shift and scale back */
12117  (*left) = (*var)->data.negate.constant - (*left);
12118  (*right) = (*var)->data.negate.constant - (*right);
12119 
12120  *var = (*var)->negatedvar;
12121 
12122  /* through the negated variable the left and right interval bound have to swapped */
12123  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12124  break;
12125 
12126  default:
12127  SCIPerrorMessage("unknown variable status\n");
12128  return SCIP_INVALIDDATA;
12129  }
12130 
12131  return SCIP_OKAY;
12132 }
12133 
12134 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12135  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12136  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12137  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12138  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12139  */
12141  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12142  SCIP_SET* set, /**< global SCIP settings */
12143  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12144  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12145  )
12146 {
12147  assert(var != NULL);
12148  assert(scalar != NULL);
12149  assert(constant != NULL);
12150 
12151  while( *var != NULL )
12152  {
12153  switch( SCIPvarGetStatus(*var) )
12154  {
12156  if( (*var)->data.original.transvar == NULL )
12157  {
12158  SCIPerrorMessage("original variable has no transformed variable attached\n");
12159  return SCIP_INVALIDDATA;
12160  }
12161  *var = (*var)->data.original.transvar;
12162  break;
12163 
12164  case SCIP_VARSTATUS_LOOSE:
12165  case SCIP_VARSTATUS_COLUMN:
12166  return SCIP_OKAY;
12167 
12168  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12169  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12170  {
12171  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12172  {
12173  assert(*scalar != 0.0);
12174  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12175  (*constant) = SCIPsetInfinity(set);
12176  else
12177  (*constant) = -SCIPsetInfinity(set);
12178  }
12179  else
12180  (*constant) += *scalar * (*var)->glbdom.lb;
12181  }
12182 #ifndef NDEBUG
12183  else
12184  {
12185  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12186  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12187  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12188  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12189  }
12190 #endif
12191  *scalar = 0.0;
12192  return SCIP_OKAY;
12193 
12195  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12196  if ( (*var)->data.multaggr.nvars == 1 )
12197  {
12198  assert((*var)->data.multaggr.vars != NULL);
12199  assert((*var)->data.multaggr.scalars != NULL);
12200  assert((*var)->data.multaggr.vars[0] != NULL);
12201  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12202  {
12203  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12204  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12205  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12206  */
12207  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12208  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12209  {
12210  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12211  {
12212  assert(!SCIPsetIsInfinity(set, -(*constant)));
12213  (*constant) = SCIPsetInfinity(set);
12214  }
12215  else
12216  {
12217  assert(!SCIPsetIsInfinity(set, *constant));
12218  (*constant) = -SCIPsetInfinity(set);
12219  }
12220  (*scalar) = 0.0;
12221  }
12222  else
12223  (*constant) += *scalar * (*var)->data.multaggr.constant;
12224  }
12225  (*scalar) *= (*var)->data.multaggr.scalars[0];
12226  *var = (*var)->data.multaggr.vars[0];
12227  break;
12228  }
12229  return SCIP_OKAY;
12230 
12231  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12232  assert((*var)->data.aggregate.var != NULL);
12233  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12234  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12235  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12236  (*constant) += *scalar * (*var)->data.aggregate.constant;
12237  (*scalar) *= (*var)->data.aggregate.scalar;
12238  *var = (*var)->data.aggregate.var;
12239  break;
12240 
12241  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12242  assert((*var)->negatedvar != NULL);
12243  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12244  assert((*var)->negatedvar->negatedvar == *var);
12245  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12246  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12247  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12248  (*constant) += *scalar * (*var)->data.negate.constant;
12249  (*scalar) *= -1.0;
12250  *var = (*var)->negatedvar;
12251  break;
12252 
12253  default:
12254  SCIPerrorMessage("unknown variable status\n");
12255  SCIPABORT();
12256  return SCIP_INVALIDDATA; /*lint !e527*/
12257  }
12258  }
12259  *scalar = 0.0;
12260 
12261  return SCIP_OKAY;
12262 }
12263 
12264 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12265  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12266  */
12268  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12269  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12270  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12271  )
12272 {
12273  SCIP_VAR* parentvar;
12274 
12275  assert(var != NULL);
12276  assert(*var != NULL);
12277  assert(scalar != NULL);
12278  assert(constant != NULL);
12279 
12280  while( !SCIPvarIsOriginal(*var) )
12281  {
12282  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12283  * var
12284  */
12285  if( (*var)->nparentvars == 0 )
12286  {
12287  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12288  * space
12289  */
12291  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12292  {
12293  *scalar *= -1.0;
12294  *constant -= (*var)->data.negate.constant * (*scalar);
12295  *var = (*var)->negatedvar;
12296 
12297  continue;
12298  }
12299  /* if the variables does not have any parent the variables was created during solving and has no original
12300  * counterpart
12301  */
12302  else
12303  {
12304  *var = NULL;
12305 
12306  return SCIP_OKAY;
12307  }
12308  }
12309 
12310  /* follow the link to the first parent variable */
12311  parentvar = (*var)->parentvars[0];
12312  assert(parentvar != NULL);
12313 
12314  switch( SCIPvarGetStatus(parentvar) )
12315  {
12317  break;
12318 
12319  case SCIP_VARSTATUS_COLUMN:
12320  case SCIP_VARSTATUS_LOOSE:
12321  case SCIP_VARSTATUS_FIXED:
12323  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12324  return SCIP_INVALIDDATA;
12325 
12326  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12327  assert(parentvar->data.aggregate.var == *var);
12328  assert(parentvar->data.aggregate.scalar != 0.0);
12329  *scalar /= parentvar->data.aggregate.scalar;
12330  *constant -= parentvar->data.aggregate.constant * (*scalar);
12331  break;
12332 
12333  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12334  assert(parentvar->negatedvar != NULL);
12335  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12336  assert(parentvar->negatedvar->negatedvar == parentvar);
12337  *scalar *= -1.0;
12338  *constant -= parentvar->data.negate.constant * (*scalar);
12339  break;
12340 
12341  default:
12342  SCIPerrorMessage("unknown variable status\n");
12343  return SCIP_INVALIDDATA;
12344  }
12345 
12346  assert( parentvar != NULL );
12347  *var = parentvar;
12348  }
12349 
12350  return SCIP_OKAY;
12351 }
12352 
12353 /** returns whether the given variable is the direct counterpart of an original problem variable */
12355  SCIP_VAR* var /**< problem variable */
12356  )
12357 {
12358  SCIP_VAR* parentvar;
12359  assert(var != NULL);
12360 
12361  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12362  return FALSE;
12363 
12364  assert(var->parentvars != NULL);
12365  parentvar = var->parentvars[0];
12366  assert(parentvar != NULL);
12367 
12368  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12369  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12370  parentvar = parentvar->parentvars[0];
12371  assert( parentvar != NULL );
12372 
12373  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12374 }
12375 
12376 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12377  * the variable's own data due to diving, that operate only on the LP without updating the variables
12378  */
12380  SCIP_VAR* var /**< problem variable */
12381  )
12382 {
12383  assert(var != NULL);
12384 
12385  /* get bounds of attached variables */
12386  switch( SCIPvarGetStatus(var) )
12387  {
12389  assert(var->data.original.transvar != NULL);
12390  return SCIPvarGetObjLP(var->data.original.transvar);
12391 
12392  case SCIP_VARSTATUS_COLUMN:
12393  assert(var->data.col != NULL);
12394  return SCIPcolGetObj(var->data.col);
12395 
12396  case SCIP_VARSTATUS_LOOSE:
12397  case SCIP_VARSTATUS_FIXED:
12398  return var->obj;
12399 
12400  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12401  assert(var->data.aggregate.var != NULL);
12402  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12403 
12405  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12406  SCIPABORT();
12407  return 0.0; /*lint !e527*/
12408 
12409  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12410  assert(var->negatedvar != NULL);
12412  assert(var->negatedvar->negatedvar == var);
12413  return -SCIPvarGetObjLP(var->negatedvar);
12414 
12415  default:
12416  SCIPerrorMessage("unknown variable status\n");
12417  SCIPABORT();
12418  return 0.0; /*lint !e527*/
12419  }
12420 }
12421 
12422 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12423  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12424  */
12426  SCIP_VAR* var, /**< problem variable */
12427  SCIP_SET* set /**< global SCIP settings */
12428  )
12429 {
12430  assert(var != NULL);
12431  assert(set != NULL);
12432  assert(var->scip == set->scip);
12433 
12434  /* get bounds of attached variables */
12435  switch( SCIPvarGetStatus(var) )
12436  {
12438  assert(var->data.original.transvar != NULL);
12439  return SCIPvarGetLbLP(var->data.original.transvar, set);
12440 
12441  case SCIP_VARSTATUS_COLUMN:
12442  assert(var->data.col != NULL);
12443  return SCIPcolGetLb(var->data.col);
12444 
12445  case SCIP_VARSTATUS_LOOSE:
12446  case SCIP_VARSTATUS_FIXED:
12447  return var->locdom.lb;
12448 
12449  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12450  assert(var->data.aggregate.var != NULL);
12451  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12452  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12453  {
12454  return -SCIPsetInfinity(set);
12455  }
12456  else if( var->data.aggregate.scalar > 0.0 )
12457  {
12458  /* a > 0 -> get lower bound of y */
12459  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12460  }
12461  else if( var->data.aggregate.scalar < 0.0 )
12462  {
12463  /* a < 0 -> get upper bound of y */
12464  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12465  }
12466  else
12467  {
12468  SCIPerrorMessage("scalar is zero in aggregation\n");
12469  SCIPABORT();
12470  return SCIP_INVALID; /*lint !e527*/
12471  }
12472 
12474  /**@todo get the sides of the corresponding linear constraint */
12475  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12476  SCIPABORT();
12477  return SCIP_INVALID; /*lint !e527*/
12478 
12479  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12480  assert(var->negatedvar != NULL);
12482  assert(var->negatedvar->negatedvar == var);
12483  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12484 
12485  default:
12486  SCIPerrorMessage("unknown variable status\n");
12487  SCIPABORT();
12488  return SCIP_INVALID; /*lint !e527*/
12489  }
12490 }
12491 
12492 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12493  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12494  */
12496  SCIP_VAR* var, /**< problem variable */
12497  SCIP_SET* set /**< global SCIP settings */
12498  )
12499 {
12500  assert(var != NULL);
12501  assert(set != NULL);
12502  assert(var->scip == set->scip);
12503 
12504  /* get bounds of attached variables */
12505  switch( SCIPvarGetStatus(var) )
12506  {
12508  assert(var->data.original.transvar != NULL);
12509  return SCIPvarGetUbLP(var->data.original.transvar, set);
12510 
12511  case SCIP_VARSTATUS_COLUMN:
12512  assert(var->data.col != NULL);
12513  return SCIPcolGetUb(var->data.col);
12514 
12515  case SCIP_VARSTATUS_LOOSE:
12516  case SCIP_VARSTATUS_FIXED:
12517  return var->locdom.ub;
12518 
12519  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12520  assert(var->data.aggregate.var != NULL);
12521  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12522  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12523  {
12524  return SCIPsetInfinity(set);
12525  }
12526  if( var->data.aggregate.scalar > 0.0 )
12527  {
12528  /* a > 0 -> get upper bound of y */
12529  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12530  }
12531  else if( var->data.aggregate.scalar < 0.0 )
12532  {
12533  /* a < 0 -> get lower bound of y */
12534  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12535  }
12536  else
12537  {
12538  SCIPerrorMessage("scalar is zero in aggregation\n");
12539  SCIPABORT();
12540  return SCIP_INVALID; /*lint !e527*/
12541  }
12542 
12544  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12545  SCIPABORT();
12546  return SCIP_INVALID; /*lint !e527*/
12547 
12548  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12549  assert(var->negatedvar != NULL);
12551  assert(var->negatedvar->negatedvar == var);
12552  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12553 
12554  default:
12555  SCIPerrorMessage("unknown variable status\n");
12556  SCIPABORT();
12557  return SCIP_INVALID; /*lint !e527*/
12558  }
12559 }
12560 
12561 /** gets primal LP solution value of variable */
12563  SCIP_VAR* var /**< problem variable */
12564  )
12565 {
12566  assert(var != NULL);
12567 
12568  switch( SCIPvarGetStatus(var) )
12569  {
12571  if( var->data.original.transvar == NULL )
12572  return SCIP_INVALID;
12573  return SCIPvarGetLPSol(var->data.original.transvar);
12574 
12575  case SCIP_VARSTATUS_LOOSE:
12576  return SCIPvarGetBestBoundLocal(var);
12577 
12578  case SCIP_VARSTATUS_COLUMN:
12579  assert(var->data.col != NULL);
12580  return SCIPcolGetPrimsol(var->data.col);
12581 
12582  case SCIP_VARSTATUS_FIXED:
12583  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12584  return var->locdom.lb;
12585 
12587  {
12588  SCIP_Real lpsolval;
12589 
12590  assert(var->data.aggregate.var != NULL);
12591  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12592 
12593  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12594  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12595  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12596  * (or is called by) a public interface method; instead, we only assert that values are finite
12597  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12598  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12599  */
12600  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12601  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12602  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12603  }
12605  {
12606  SCIP_Real primsol;
12607  int i;
12608 
12609  assert(!var->donotmultaggr);
12610  assert(var->data.multaggr.vars != NULL);
12611  assert(var->data.multaggr.scalars != NULL);
12612  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12613  * assert(var->data.multaggr.nvars >= 2);
12614  */
12615  primsol = var->data.multaggr.constant;
12616  for( i = 0; i < var->data.multaggr.nvars; ++i )
12617  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12618  return primsol;
12619  }
12620  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12621  assert(var->negatedvar != NULL);
12623  assert(var->negatedvar->negatedvar == var);
12624  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12625 
12626  default:
12627  SCIPerrorMessage("unknown variable status\n");
12628  SCIPABORT();
12629  return SCIP_INVALID; /*lint !e527*/
12630  }
12631 }
12632 
12633 /** gets primal NLP solution value of variable */
12635  SCIP_VAR* var /**< problem variable */
12636  )
12637 {
12638  SCIP_Real solval;
12639  int i;
12640 
12641  assert(var != NULL);
12642 
12643  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12644  switch( SCIPvarGetStatus(var) )
12645  {
12647  return SCIPvarGetNLPSol(var->data.original.transvar);
12648 
12649  case SCIP_VARSTATUS_LOOSE:
12650  case SCIP_VARSTATUS_COLUMN:
12651  return var->nlpsol;
12652 
12653  case SCIP_VARSTATUS_FIXED:
12654  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12655  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12656  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12657  return SCIPvarGetLbGlobal(var);
12658 
12659  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12660  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12661  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12662 
12664  solval = var->data.multaggr.constant;
12665  for( i = 0; i < var->data.multaggr.nvars; ++i )
12666  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12667  return solval;
12668 
12670  solval = SCIPvarGetNLPSol(var->negatedvar);
12671  return var->data.negate.constant - solval;
12672 
12673  default:
12674  SCIPerrorMessage("unknown variable status\n");
12675  SCIPABORT();
12676  return SCIP_INVALID; /*lint !e527*/
12677  }
12678 }
12679 
12680 /** gets pseudo solution value of variable at current node */
12681 static
12683  SCIP_VAR* var /**< problem variable */
12684  )
12685 {
12686  SCIP_Real pseudosol;
12687  int i;
12688 
12689  assert(var != NULL);
12690 
12691  switch( SCIPvarGetStatus(var) )
12692  {
12694  if( var->data.original.transvar == NULL )
12695  return SCIP_INVALID;
12697 
12698  case SCIP_VARSTATUS_LOOSE:
12699  case SCIP_VARSTATUS_COLUMN:
12700  return SCIPvarGetBestBoundLocal(var);
12701 
12702  case SCIP_VARSTATUS_FIXED:
12703  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12704  return var->locdom.lb;
12705 
12707  {
12708  SCIP_Real pseudosolval;
12709  assert(var->data.aggregate.var != NULL);
12710  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12711  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12712  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12713  * (or is called by) a public interface method; instead, we only assert that values are finite
12714  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12715  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12716  */
12717  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12718  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12719  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12720  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12721  }
12723  assert(!var->donotmultaggr);
12724  assert(var->data.multaggr.vars != NULL);
12725  assert(var->data.multaggr.scalars != NULL);
12726  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12727  * assert(var->data.multaggr.nvars >= 2);
12728  */
12729  pseudosol = var->data.multaggr.constant;
12730  for( i = 0; i < var->data.multaggr.nvars; ++i )
12731  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12732  return pseudosol;
12733 
12734  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12735  assert(var->negatedvar != NULL);
12737  assert(var->negatedvar->negatedvar == var);
12738  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12739 
12740  default:
12741  SCIPerrorMessage("unknown variable status\n");
12742  SCIPABORT();
12743  return SCIP_INVALID; /*lint !e527*/
12744  }
12745 }
12746 
12747 /** gets current LP or pseudo solution value of variable */
12749  SCIP_VAR* var, /**< problem variable */
12750  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12751  )
12752 {
12753  if( getlpval )
12754  return SCIPvarGetLPSol(var);
12755  else
12756  return SCIPvarGetPseudoSol(var);
12757 }
12758 
12759 /** remembers the current solution as root solution in the problem variables */
12760 void SCIPvarStoreRootSol(
12761  SCIP_VAR* var, /**< problem variable */
12762  SCIP_Bool roothaslp /**< is the root solution from LP? */
12763  )
12764 {
12765  assert(var != NULL);
12766 
12767  var->rootsol = SCIPvarGetSol(var, roothaslp);
12768 }
12769 
12770 /** updates the current solution as best root solution of the given variable if it is better */
12772  SCIP_VAR* var, /**< problem variable */
12773  SCIP_SET* set, /**< global SCIP settings */
12774  SCIP_Real rootsol, /**< root solution value */
12775  SCIP_Real rootredcost, /**< root reduced cost */
12776  SCIP_Real rootlpobjval /**< objective value of the root LP */
12777  )
12778 {
12779  assert(var != NULL);
12780  assert(set != NULL);
12781  assert(var->scip == set->scip);
12782 
12783  /* if reduced cost are zero nothing to update */
12784  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12785  return;
12786 
12787  /* check if we have already a best combination stored */
12788  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12789  {
12790  SCIP_Real currcutoffbound;
12791  SCIP_Real cutoffbound;
12792  SCIP_Real bound;
12793 
12794  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12795  * root reduced cost, and root LP objective value combination
12796  */
12797  if( var->bestrootredcost > 0.0 )
12798  bound = SCIPvarGetUbGlobal(var);
12799  else
12800  bound = SCIPvarGetLbGlobal(var);
12801 
12802  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12803 
12804  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12805  * cost, and root LP objective value combination
12806  */
12807  if( rootredcost > 0.0 )
12808  bound = SCIPvarGetUbGlobal(var);
12809  else
12810  bound = SCIPvarGetLbGlobal(var);
12811 
12812  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12813 
12814  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12815  if( cutoffbound > currcutoffbound )
12816  {
12817  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12818  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12819 
12820  var->bestrootsol = rootsol;
12821  var->bestrootredcost = rootredcost;
12822  var->bestrootlpobjval = rootlpobjval;
12823  }
12824  }
12825  else
12826  {
12827  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12828  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12829  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12830  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12831 
12832  var->bestrootsol = rootsol;
12833  var->bestrootredcost = rootredcost;
12834  var->bestrootlpobjval = rootlpobjval;
12835  }
12836 }
12837 
12838 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12839  * completely solved, zero is returned
12840  */
12842  SCIP_VAR* var /**< problem variable */
12843  )
12844 {
12845  SCIP_Real rootsol;
12846  int i;
12847 
12848  assert(var != NULL);
12849 
12850  switch( SCIPvarGetStatus(var) )
12851  {
12853  if( var->data.original.transvar == NULL )
12854  return 0.0;
12855  return SCIPvarGetRootSol(var->data.original.transvar);
12856 
12857  case SCIP_VARSTATUS_LOOSE:
12858  case SCIP_VARSTATUS_COLUMN:
12859  return var->rootsol;
12860 
12861  case SCIP_VARSTATUS_FIXED:
12862  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12863  return var->locdom.lb;
12864 
12866  assert(var->data.aggregate.var != NULL);
12867  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12868  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12869  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12870  * (or is called by) a public interface method; instead, we only assert that values are finite
12871  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12872  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12873  */
12877 
12879  assert(!var->donotmultaggr);
12880  assert(var->data.multaggr.vars != NULL);
12881  assert(var->data.multaggr.scalars != NULL);
12882  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12883  * assert(var->data.multaggr.nvars >= 2);
12884  */
12885  rootsol = var->data.multaggr.constant;
12886  for( i = 0; i < var->data.multaggr.nvars; ++i )
12887  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12888  return rootsol;
12889 
12890  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12891  assert(var->negatedvar != NULL);
12893  assert(var->negatedvar->negatedvar == var);
12894  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12895 
12896  default:
12897  SCIPerrorMessage("unknown variable status\n");
12898  SCIPABORT();
12899  return SCIP_INVALID; /*lint !e527*/
12900  }
12901 }
12902 
12903 /** returns for given variable the reduced cost */
12904 static
12906  SCIP_VAR* var, /**< problem variable */
12907  SCIP_SET* set, /**< global SCIP settings */
12908  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12909  SCIP_STAT* stat, /**< problem statistics */
12910  SCIP_LP* lp /**< current LP data */
12911  )
12912 {
12914  {
12915  SCIP_COL* col;
12916  SCIP_Real primsol;
12917  SCIP_BASESTAT basestat;
12918  SCIP_Bool lpissolbasic;
12919 
12920  col = SCIPvarGetCol(var);
12921  assert(col != NULL);
12922 
12923  basestat = SCIPcolGetBasisStatus(col);
12924  lpissolbasic = SCIPlpIsSolBasic(lp);
12925  primsol = SCIPcolGetPrimsol(col);
12926 
12927  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12928  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12929  {
12930  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12931 
12932  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12933  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12935  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12936  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12937  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12938 
12939  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12940  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12941  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12942  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12943  return redcost;
12944  else
12945  return 0.0;
12946  }
12947 
12948  return 0.0;
12949  }
12950 
12951  return 0.0;
12952 }
12953 
12954 #define MAX_CLIQUELENGTH 50
12955 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12956  * the binary variable is fixed to the given value
12957  */
12959  SCIP_VAR* var, /**< problem variable */
12960  SCIP_SET* set, /**< global SCIP settings */
12961  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12962  SCIP_STAT* stat, /**< problem statistics */
12963  SCIP_PROB* prob, /**< transformed problem, or NULL */
12964  SCIP_LP* lp /**< current LP data */
12965  )
12966 {
12967  SCIP_Real implredcost;
12968  int ncliques;
12969  int nvars;
12970 
12971  assert(SCIPvarIsBinary(var));
12972  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12973 
12974  /* get reduced cost of given variable */
12975  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12976 
12977 #ifdef SCIP_MORE_DEBUG
12978  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12979 #endif
12980 
12981  /* the following algorithm is expensive */
12982  ncliques = SCIPvarGetNCliques(var, varfixing);
12983 
12984  if( ncliques > 0 )
12985  {
12986  SCIP_CLIQUE** cliques;
12987  SCIP_CLIQUE* clique;
12988  SCIP_VAR** clqvars;
12989  SCIP_VAR** probvars;
12990  SCIP_VAR* clqvar;
12991  SCIP_Bool* clqvalues;
12992  int* entries;
12993  int* ids;
12994  SCIP_Real redcost;
12995  SCIP_Bool cleanedup;
12996  int nclqvars;
12997  int nentries;
12998  int nids;
12999  int id;
13000  int c;
13001  int v;
13002 
13003  assert(prob != NULL);
13004  assert(SCIPprobIsTransformed(prob));
13005 
13006  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13007 
13008  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13009  nids = 0;
13010  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13011 
13012  cliques = SCIPvarGetCliques(var, varfixing);
13013  assert(cliques != NULL);
13014 
13015  for( c = ncliques - 1; c >= 0; --c )
13016  {
13017  clique = cliques[c];
13018  assert(clique != NULL);
13019  nclqvars = SCIPcliqueGetNVars(clique);
13020  assert(nclqvars > 0);
13021 
13022  if( nclqvars > MAX_CLIQUELENGTH )
13023  continue;
13024 
13025  clqvars = SCIPcliqueGetVars(clique);
13026  clqvalues = SCIPcliqueGetValues(clique);
13027  assert(clqvars != NULL);
13028  assert(clqvalues != NULL);
13029 
13030  cleanedup = SCIPcliqueIsCleanedUp(clique);
13031 
13032  for( v = nclqvars - 1; v >= 0; --v )
13033  {
13034  clqvar = clqvars[v];
13035  assert(clqvar != NULL);
13036 
13037  /* ignore binary variable which are fixed */
13038  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13039  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13040  {
13041  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13042  assert(0 < probindex && probindex < nentries);
13043 
13044 #if 0
13045  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13046  * can appear since there is no guarantee that all these infeasible bounds were found
13047  */
13048  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13049 #endif
13050  if( entries[probindex] == 0 )
13051  {
13052  ids[nids] = probindex;
13053  ++nids;
13054 
13055  /* mark variable as visited */
13056  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13057  }
13058  }
13059  }
13060  }
13061 
13062  probvars = SCIPprobGetVars(prob);
13063  assert(probvars != NULL);
13064 
13065  /* add all implied reduced cost */
13066  for( v = nids - 1; v >= 0; --v )
13067  {
13068  id = ids[v];
13069  assert(0 < id && id < nentries);
13070  assert(entries[id] != 0);
13071  assert(probvars[id - 1] != NULL);
13072  assert(SCIPvarIsActive(probvars[id - 1]));
13073  assert(SCIPvarIsBinary(probvars[id - 1]));
13074  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13075 
13076  if( (entries[id] > 0) != varfixing )
13077  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13078  else
13079  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13080 
13081  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13082  implredcost += redcost;
13083 
13084  /* reset entries clear buffer array */
13085  entries[id] = 0;
13086  }
13087 
13088  SCIPsetFreeCleanBufferArray(set, &entries);
13089  SCIPsetFreeBufferArray(set, &ids);
13090  }
13091 
13092 #ifdef SCIP_MORE_DEBUG
13093  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13094  implredcost);
13095 #endif
13096 
13097  /* collect non-binary implication information */
13098  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13099 
13100  if( nvars > 0 )
13101  {
13102  SCIP_VAR** vars;
13103  SCIP_VAR* implvar;
13104  SCIP_COL* col;
13105  SCIP_Real* bounds;
13106  SCIP_BOUNDTYPE* boundtypes;
13107  SCIP_Real redcost;
13108  SCIP_Real lb;
13109  SCIP_Real ub;
13110  SCIP_Bool lpissolbasic;
13111  int v;
13112 
13113  vars = SCIPimplicsGetVars(var->implics, varfixing);
13114  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13115  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13116  lpissolbasic = SCIPlpIsSolBasic(lp);
13117 
13118  for( v = nvars - 1; v >= 0; --v )
13119  {
13120  implvar = vars[v];
13121  assert(implvar != NULL);
13122 
13123  lb = SCIPvarGetLbLocal(implvar);
13124  ub = SCIPvarGetUbLocal(implvar);
13125 
13126  /* ignore binary variable which are fixed or not of column status */
13127  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13128  continue;
13129 
13130  col = SCIPvarGetCol(implvar);
13131  assert(col != NULL);
13132  redcost = 0.0;
13133 
13134  /* solved lp with basis information or not? */
13135  if( lpissolbasic )
13136  {
13137  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13138 
13139  /* check if the implication is not not yet applied */
13140  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13141  {
13142  redcost = SCIPcolGetRedcost(col, stat, lp);
13143  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13144 
13145  if( !varfixing )
13146  redcost *= (lb - bounds[v]);
13147  else
13148  redcost *= (bounds[v] - lb);
13149  }
13150  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13151  {
13152  redcost = SCIPcolGetRedcost(col, stat, lp);
13153  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13154 
13155  if( varfixing )
13156  redcost *= (bounds[v] - ub);
13157  else
13158  redcost *= (ub - bounds[v]);
13159  }
13160  }
13161  else
13162  {
13163  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13164 
13165  /* check if the implication is not not yet applied */
13166  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13167  {
13168  redcost = SCIPcolGetRedcost(col, stat, lp);
13169  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13170 
13171  if( varfixing )
13172  redcost *= (lb - bounds[v]);
13173  else
13174  redcost *= (bounds[v] - lb);
13175  }
13176  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13177  {
13178  redcost = SCIPcolGetRedcost(col, stat, lp);
13179  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13180 
13181  if( varfixing )
13182  redcost *= (bounds[v] - ub);
13183  else
13184  redcost *= (ub - bounds[v]);
13185  }
13186  }
13187 
13188  /* improve implied reduced cost */
13189  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13190  implredcost += redcost;
13191  }
13192  }
13193 
13194 #ifdef SCIP_MORE_DEBUG
13195  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13196  SCIPvarGetName(var), ncliques, nvars, implredcost);
13197 #endif
13198 
13199  return implredcost;
13200 }
13201 
13202 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13203  * the root relaxation is not yet completely solved, zero is returned
13204  */
13206  SCIP_VAR* var /**< problem variable */
13207  )
13208 {
13209  SCIP_Real rootsol;
13210  int i;
13211 
13212  assert(var != NULL);
13213 
13214  switch( SCIPvarGetStatus(var) )
13215  {
13217  if( var->data.original.transvar == NULL )
13218  return 0.0;
13220 
13221  case SCIP_VARSTATUS_LOOSE:
13222  case SCIP_VARSTATUS_COLUMN:
13223  return var->bestrootsol;
13224 
13225  case SCIP_VARSTATUS_FIXED:
13226  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13227  return var->locdom.lb;
13228 
13230  assert(var->data.aggregate.var != NULL);
13231  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13232  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13233  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13234  * (or is called by) a public interface method; instead, we only assert that values are finite
13235  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13236  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13237  */
13241 
13243  assert(!var->donotmultaggr);
13244  assert(var->data.multaggr.vars != NULL);
13245  assert(var->data.multaggr.scalars != NULL);
13246  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13247  * assert(var->data.multaggr.nvars >= 2);
13248  */
13249  rootsol = var->data.multaggr.constant;
13250  for( i = 0; i < var->data.multaggr.nvars; ++i )
13251  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13252  return rootsol;
13253 
13254  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13255  assert(var->negatedvar != NULL);
13257  assert(var->negatedvar->negatedvar == var);
13258  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13259 
13260  default:
13261  SCIPerrorMessage("unknown variable status\n");
13262  SCIPABORT();
13263  return 0.0; /*lint !e527*/
13264  }
13265 }
13266 
13267 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13268  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13269  * returned
13270  */
13272  SCIP_VAR* var /**< problem variable */
13273  )
13274 {
13275  assert(var != NULL);
13276 
13277  switch( SCIPvarGetStatus(var) )
13278  {
13280  if( var->data.original.transvar == NULL )
13281  return SCIP_INVALID;
13283 
13284  case SCIP_VARSTATUS_LOOSE:
13285  case SCIP_VARSTATUS_COLUMN:
13286  return var->bestrootredcost;
13287 
13288  case SCIP_VARSTATUS_FIXED:
13292  return 0.0;
13293 
13294  default:
13295  SCIPerrorMessage("unknown variable status\n");
13296  SCIPABORT();
13297  return 0.0; /*lint !e527*/
13298  }
13299 }
13300 
13301 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13302  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13303  * SCIP_INVALID is returned
13304  */
13306  SCIP_VAR* var /**< problem variable */
13307  )
13308 {
13309  assert(var != NULL);
13310 
13311  switch( SCIPvarGetStatus(var) )
13312  {
13314  if( var->data.original.transvar == NULL )
13315  return SCIP_INVALID;
13317 
13318  case SCIP_VARSTATUS_LOOSE:
13319  case SCIP_VARSTATUS_COLUMN:
13320  return var->bestrootlpobjval;
13321 
13322  case SCIP_VARSTATUS_FIXED:
13326  return SCIP_INVALID;
13327 
13328  default:
13329  SCIPerrorMessage("unknown variable status\n");
13330  SCIPABORT();
13331  return SCIP_INVALID; /*lint !e527*/
13332  }
13333 }
13334 
13335 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13337  SCIP_VAR* var, /**< problem variable */
13338  SCIP_Real rootsol, /**< root solution value */
13339  SCIP_Real rootredcost, /**< root reduced cost */
13340  SCIP_Real rootlpobjval /**< objective value of the root LP */
13341  )
13342 {
13343  assert(var != NULL);
13344 
13345  var->bestrootsol = rootsol;
13346  var->bestrootredcost = rootredcost;
13347  var->bestrootlpobjval = rootlpobjval;
13348 }
13349 
13350 /** stores the solution value as relaxation solution in the problem variable */
13352  SCIP_VAR* var, /**< problem variable */
13353  SCIP_SET* set, /**< global SCIP settings */
13354  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13355  SCIP_Real solval, /**< solution value in the current relaxation solution */
13356  SCIP_Bool updateobj /**< should the objective value be updated? */
13357  )
13358 {
13359  assert(var != NULL);
13360  assert(relaxation != NULL);
13361  assert(set != NULL);
13362  assert(var->scip == set->scip);
13363 
13364  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13365  switch( SCIPvarGetStatus(var) )
13366  {
13368  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13369  break;
13370 
13371  case SCIP_VARSTATUS_LOOSE:
13372  case SCIP_VARSTATUS_COLUMN:
13373  if( updateobj )
13374  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13375  var->relaxsol = solval;
13376  break;
13377 
13378  case SCIP_VARSTATUS_FIXED:
13379  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13380  {
13381  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13382  SCIPvarGetName(var), var->glbdom.lb, solval);
13383  return SCIP_INVALIDDATA;
13384  }
13385  break;
13386 
13387  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13388  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13389  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13390  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13391  break;
13393  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13394  return SCIP_INVALIDDATA;
13395 
13397  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13398  break;
13399 
13400  default:
13401  SCIPerrorMessage("unknown variable status\n");
13402  return SCIP_INVALIDDATA;
13403  }
13404 
13405  return SCIP_OKAY;
13406 }
13407 
13408 /** returns the solution value of the problem variable in the relaxation solution
13409  *
13410  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13411  */
13413  SCIP_VAR* var, /**< problem variable */
13414  SCIP_SET* set /**< global SCIP settings */
13415  )
13416 {
13417  SCIP_Real solvalsum;
13418  SCIP_Real solval;
13419  int i;
13420 
13421  assert(var != NULL);
13422  assert(set != NULL);
13423  assert(var->scip == set->scip);
13424 
13425  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13426  switch( SCIPvarGetStatus(var) )
13427  {
13429  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13430 
13431  case SCIP_VARSTATUS_LOOSE:
13432  case SCIP_VARSTATUS_COLUMN:
13433  return var->relaxsol;
13434 
13435  case SCIP_VARSTATUS_FIXED:
13436  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13437  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13438  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13439  return SCIPvarGetLbGlobal(var);
13440 
13441  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13442  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13443  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13444  {
13445  if( var->data.aggregate.scalar * solval > 0.0 )
13446  return SCIPsetInfinity(set);
13447  if( var->data.aggregate.scalar * solval < 0.0 )
13448  return -SCIPsetInfinity(set);
13449  }
13450  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13451 
13453  solvalsum = var->data.multaggr.constant;
13454  for( i = 0; i < var->data.multaggr.nvars; ++i )
13455  {
13456  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13457  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13458  {
13459  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13460  return SCIPsetInfinity(set);
13461  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13462  return -SCIPsetInfinity(set);
13463  }
13464  solvalsum += var->data.multaggr.scalars[i] * solval;
13465  }
13466  return solvalsum;
13467 
13469  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13470  if( SCIPsetIsInfinity(set, solval) )
13471  return -SCIPsetInfinity(set);
13472  if( SCIPsetIsInfinity(set, -solval) )
13473  return SCIPsetInfinity(set);
13474  return var->data.negate.constant - solval;
13475 
13476  default:
13477  SCIPerrorMessage("unknown variable status\n");
13478  SCIPABORT();
13479  return SCIP_INVALID; /*lint !e527*/
13480  }
13481 }
13482 
13483 /** returns the solution value of the transformed problem variable in the relaxation solution */
13485  SCIP_VAR* var /**< problem variable */
13486  )
13487 {
13488  assert(var != NULL);
13490 
13491  return var->relaxsol;
13492 }
13493 
13494 /** stores the solution value as NLP solution in the problem variable */
13496  SCIP_VAR* var, /**< problem variable */
13497  SCIP_SET* set, /**< global SCIP settings */
13498  SCIP_Real solval /**< solution value in the current NLP solution */
13499  )
13500 {
13501  assert(var != NULL);
13502  assert(set != NULL);
13503  assert(var->scip == set->scip);
13504 
13505  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13506  switch( SCIPvarGetStatus(var) )
13507  {
13509  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13510  break;
13511 
13512  case SCIP_VARSTATUS_LOOSE:
13513  case SCIP_VARSTATUS_COLUMN:
13514  var->nlpsol = solval;
13515  break;
13516 
13517  case SCIP_VARSTATUS_FIXED:
13518  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13519  {
13520  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13521  SCIPvarGetName(var), var->glbdom.lb, solval);
13522  SCIPABORT();
13523  return SCIP_INVALIDCALL; /*lint !e527*/
13524  }
13525  break;
13526 
13527  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13528  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13529  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13530  break;
13531 
13533  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13534  SCIPABORT();
13535  return SCIP_INVALIDCALL; /*lint !e527*/
13536 
13538  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13539  break;
13540 
13541  default:
13542  SCIPerrorMessage("unknown variable status\n");
13543  SCIPABORT();
13544  return SCIP_ERROR; /*lint !e527*/
13545  }
13546 
13547  return SCIP_OKAY;
13548 }
13549 
13550 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13552  SCIP_VAR* var /**< problem variable */
13553  )
13554 {
13555  SCIP_Real avgsol;
13556  int i;
13557 
13558  assert(var != NULL);
13559 
13560  switch( SCIPvarGetStatus(var) )
13561  {
13563  if( var->data.original.transvar == NULL )
13564  return 0.0;
13565  return SCIPvarGetAvgSol(var->data.original.transvar);
13566 
13567  case SCIP_VARSTATUS_LOOSE:
13568  case SCIP_VARSTATUS_COLUMN:
13569  avgsol = var->primsolavg;
13570  avgsol = MAX(avgsol, var->glbdom.lb);
13571  avgsol = MIN(avgsol, var->glbdom.ub);
13572  return avgsol;
13573 
13574  case SCIP_VARSTATUS_FIXED:
13575  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13576  return var->locdom.lb;
13577 
13579  assert(var->data.aggregate.var != NULL);
13580  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13581  + var->data.aggregate.constant;
13582 
13584  assert(!var->donotmultaggr);
13585  assert(var->data.multaggr.vars != NULL);
13586  assert(var->data.multaggr.scalars != NULL);
13587  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13588  * assert(var->data.multaggr.nvars >= 2);
13589  */
13590  avgsol = var->data.multaggr.constant;
13591  for( i = 0; i < var->data.multaggr.nvars; ++i )
13592  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13593  return avgsol;
13594 
13595  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13596  assert(var->negatedvar != NULL);
13598  assert(var->negatedvar->negatedvar == var);
13599  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13600 
13601  default:
13602  SCIPerrorMessage("unknown variable status\n");
13603  SCIPABORT();
13604  return 0.0; /*lint !e527*/
13605  }
13606 }
13607 
13608 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13609  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13610  */
13612  SCIP_VAR* var, /**< active problem variable */
13613  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13614  SCIP_SET* set, /**< global SCIP settings */
13615  SCIP_STAT* stat, /**< problem statistics */
13616  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13617  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13618  )
13619 {
13620  int nvlbs;
13621 
13622  assert(var != NULL);
13623  assert(stat != NULL);
13624  assert(set != NULL);
13625  assert(var->scip == set->scip);
13626  assert(closestvlb != NULL);
13627  assert(closestvlbidx != NULL);
13628 
13629  *closestvlbidx = -1;
13630  *closestvlb = SCIP_REAL_MIN;
13631 
13632  nvlbs = SCIPvarGetNVlbs(var);
13633  if( nvlbs > 0 )
13634  {
13635  SCIP_VAR** vlbvars;
13636  SCIP_Real* vlbcoefs;
13637  SCIP_Real* vlbconsts;
13638  int i;
13639 
13640  vlbvars = SCIPvarGetVlbVars(var);
13641  vlbcoefs = SCIPvarGetVlbCoefs(var);
13642  vlbconsts = SCIPvarGetVlbConstants(var);
13643 
13644  /* check for cached values */
13645  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13646  {
13647  i = var->closestvlbidx;
13648  assert(0 <= i && i < nvlbs);
13649  assert(SCIPvarIsActive(vlbvars[i]));
13650  *closestvlbidx = i;
13651  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13652  }
13653  else
13654  {
13655  /* search best VUB */
13656  for( i = 0; i < nvlbs; i++ )
13657  {
13658  if( SCIPvarIsActive(vlbvars[i]) )
13659  {
13660  SCIP_Real vlbsol;
13661 
13662  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13663  if( vlbsol > *closestvlb )
13664  {
13665  *closestvlb = vlbsol;
13666  *closestvlbidx = i;
13667  }
13668  }
13669  }
13670 
13671  if( sol == NULL )
13672  {
13673  /* update cached value */
13674  if( var->closestvblpcount != stat->lpcount )
13675  var->closestvubidx = -1;
13676  var->closestvlbidx = *closestvlbidx;
13677  var->closestvblpcount = stat->lpcount;
13678  }
13679  }
13680  }
13681 }
13682 
13683 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13684  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13685  */
13687  SCIP_VAR* var, /**< active problem variable */
13688  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13689  SCIP_SET* set, /**< global SCIP settings */
13690  SCIP_STAT* stat, /**< problem statistics */
13691  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13692  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13693  )
13694 {
13695  int nvubs;
13696 
13697  assert(var != NULL);
13698  assert(set != NULL);
13699  assert(var->scip == set->scip);
13700  assert(closestvub != NULL);
13701  assert(closestvubidx != NULL);
13702 
13703  *closestvubidx = -1;
13704  *closestvub = SCIP_REAL_MAX;
13705 
13706  nvubs = SCIPvarGetNVubs(var);
13707  if( nvubs > 0 )
13708  {
13709  SCIP_VAR** vubvars;
13710  SCIP_Real* vubcoefs;
13711  SCIP_Real* vubconsts;
13712  int i;
13713 
13714  vubvars = SCIPvarGetVubVars(var);
13715  vubcoefs = SCIPvarGetVubCoefs(var);
13716  vubconsts = SCIPvarGetVubConstants(var);
13717 
13718  /* check for cached values */
13719  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13720  {
13721  i = var->closestvubidx;
13722  assert(0 <= i && i < nvubs);
13723  assert(SCIPvarIsActive(vubvars[i]));
13724  *closestvubidx = i;
13725  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13726  }
13727  else
13728  {
13729  /* search best VUB */
13730  for( i = 0; i < nvubs; i++ )
13731  {
13732  if( SCIPvarIsActive(vubvars[i]) )
13733  {
13734  SCIP_Real vubsol;
13735 
13736  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13737  if( vubsol < *closestvub )
13738  {
13739  *closestvub = vubsol;
13740  *closestvubidx = i;
13741  }
13742  }
13743  }
13744 
13745  if( sol == NULL )
13746  {
13747  /* update cached value */
13748  if( var->closestvblpcount != stat->lpcount )
13749  var->closestvlbidx = -1;
13750  var->closestvubidx = *closestvubidx;
13751  var->closestvblpcount = stat->lpcount;
13752  }
13753  }
13754  }
13755 }
13756 
13757 /** resolves variable to columns and adds them with the coefficient to the row */
13759  SCIP_VAR* var, /**< problem variable */
13760  BMS_BLKMEM* blkmem, /**< block memory */
13761  SCIP_SET* set, /**< global SCIP settings */
13762  SCIP_STAT* stat, /**< problem statistics */
13763  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13764  SCIP_PROB* prob, /**< problem data */
13765  SCIP_LP* lp, /**< current LP data */
13766  SCIP_ROW* row, /**< LP row */
13767  SCIP_Real val /**< value of coefficient */
13768  )
13769 {
13770  int i;
13771 
13772  assert(var != NULL);
13773  assert(set != NULL);
13774  assert(var->scip == set->scip);
13775  assert(row != NULL);
13776  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13777 
13778  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13779 
13780  if ( SCIPsetIsZero(set, val) )
13781  return SCIP_OKAY;
13782 
13783  switch( SCIPvarGetStatus(var) )
13784  {
13786  if( var->data.original.transvar == NULL )
13787  {
13788  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13789  return SCIP_INVALIDDATA;
13790  }
13791  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13792  return SCIP_OKAY;
13793 
13794  case SCIP_VARSTATUS_LOOSE:
13795  /* add globally fixed variables as constant */
13796  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13797  {
13798  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13799  return SCIP_OKAY;
13800  }
13801  /* convert loose variable into column */
13802  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13803  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13804  /*lint -fallthrough*/
13805 
13806  case SCIP_VARSTATUS_COLUMN:
13807  assert(var->data.col != NULL);
13808  assert(var->data.col->var == var);
13809  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13810  return SCIP_OKAY;
13811 
13812  case SCIP_VARSTATUS_FIXED:
13813  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13814  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13815  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13816  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13817  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13818  return SCIP_OKAY;
13819 
13821  assert(var->data.aggregate.var != NULL);
13822  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13823  row, var->data.aggregate.scalar * val) );
13824  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13825  return SCIP_OKAY;
13826 
13828  assert(!var->donotmultaggr);
13829  assert(var->data.multaggr.vars != NULL);
13830  assert(var->data.multaggr.scalars != NULL);
13831  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13832  * assert(var->data.multaggr.nvars >= 2);
13833  */
13834  for( i = 0; i < var->data.multaggr.nvars; ++i )
13835  {
13836  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13837  row, var->data.multaggr.scalars[i] * val) );
13838  }
13839  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13840  return SCIP_OKAY;
13841 
13842  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13843  assert(var->negatedvar != NULL);
13845  assert(var->negatedvar->negatedvar == var);
13846  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13847  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13848  return SCIP_OKAY;
13849 
13850  default:
13851  SCIPerrorMessage("unknown variable status\n");
13852  return SCIP_INVALIDDATA;
13853  }
13854 }
13855 
13856 /* optionally, define this compiler flag to write complete variable histories to a file */
13857 #ifdef SCIP_HISTORYTOFILE
13858 SCIP_Longint counter = 0l;
13859 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13860 #include "scip/scip.h"
13861 #endif
13862 
13863 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13864  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13865  */
13867  SCIP_VAR* var, /**< problem variable */
13868  SCIP_SET* set, /**< global SCIP settings */
13869  SCIP_STAT* stat, /**< problem statistics */
13870  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13871  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13872  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13873  )
13874 {
13875  SCIP_Real oldrootpseudocosts;
13876  assert(var != NULL);
13877  assert(set != NULL);
13878  assert(var->scip == set->scip);
13879  assert(stat != NULL);
13880 
13881  /* check if history statistics should be collected for a variable */
13882  if( !stat->collectvarhistory )
13883  return SCIP_OKAY;
13884 
13885  switch( SCIPvarGetStatus(var) )
13886  {
13888  if( var->data.original.transvar == NULL )
13889  {
13890  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13891  return SCIP_INVALIDDATA;
13892  }
13893  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13894  return SCIP_OKAY;
13895 
13896  case SCIP_VARSTATUS_LOOSE:
13897  case SCIP_VARSTATUS_COLUMN:
13898  /* store old pseudo-costs for root LP best-estimate update */
13899  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13900 
13901  /* update history */
13902  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13903  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13904  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13905  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13906 
13907  /* update root LP best-estimate */
13908  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13909 
13910  /* append history to file */
13911 #ifdef SCIP_HISTORYTOFILE
13912  {
13913  FILE* f;
13914  char filename[256];
13915  SCIP_NODE* currentnode;
13916  SCIP_NODE* parentnode;
13917  currentnode = SCIPgetFocusNode(set->scip);
13918  parentnode = SCIPnodeGetParent(currentnode);
13919 
13920  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13921  f = fopen(filename, "a");
13922  if( NULL != f )
13923  {
13924  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13925  ++counter,
13926  SCIPvarGetName(var),
13927  SCIPnodeGetNumber(currentnode),
13928  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13929  SCIPgetNLPIterations(set->scip),
13930  SCIPgetDepth(set->scip),
13931  objdelta,
13932  solvaldelta);
13933  fclose(f);
13934  }
13935  }
13936 #endif
13937  return SCIP_OKAY;
13938 
13939  case SCIP_VARSTATUS_FIXED:
13940  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13941  return SCIP_INVALIDDATA;
13942 
13944  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13946  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13947  return SCIP_OKAY;
13948 
13950  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13951  return SCIP_INVALIDDATA;
13952 
13954  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13955  return SCIP_OKAY;
13956 
13957  default:
13958  SCIPerrorMessage("unknown variable status\n");
13959  return SCIP_INVALIDDATA;
13960  }
13961 }
13962 
13963 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13965  SCIP_VAR* var, /**< problem variable */
13966  SCIP_STAT* stat, /**< problem statistics */
13967  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13968  )
13969 {
13970  SCIP_BRANCHDIR dir;
13971 
13972  assert(var != NULL);
13973  assert(stat != NULL);
13974 
13975  switch( SCIPvarGetStatus(var) )
13976  {
13978  if( var->data.original.transvar == NULL )
13979  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13980  else
13981  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13982 
13983  case SCIP_VARSTATUS_LOOSE:
13984  case SCIP_VARSTATUS_COLUMN:
13985  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13986 
13987  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13988  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13989  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13990 
13991  case SCIP_VARSTATUS_FIXED:
13992  return 0.0;
13993 
13995  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13996 
13998  return 0.0;
13999 
14001  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14002 
14003  default:
14004  SCIPerrorMessage("unknown variable status\n");
14005  SCIPABORT();
14006  return 0.0; /*lint !e527*/
14007  }
14008 }
14009 
14010 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14011  * only using the pseudo cost information of the current run
14012  */
14014  SCIP_VAR* var, /**< problem variable */
14015  SCIP_STAT* stat, /**< problem statistics */
14016  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14017  )
14018 {
14019  SCIP_BRANCHDIR dir;
14020 
14021  assert(var != NULL);
14022  assert(stat != NULL);
14023 
14024  switch( SCIPvarGetStatus(var) )
14025  {
14027  if( var->data.original.transvar == NULL )
14028  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14029  else
14030  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14031 
14032  case SCIP_VARSTATUS_LOOSE:
14033  case SCIP_VARSTATUS_COLUMN:
14034  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14035 
14036  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14037  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14038  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14039 
14040  case SCIP_VARSTATUS_FIXED:
14041  return 0.0;
14042 
14044  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14045 
14047  return 0.0;
14048 
14050  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14051 
14052  default:
14053  SCIPerrorMessage("unknown variable status\n");
14054  SCIPABORT();
14055  return 0.0; /*lint !e527*/
14056  }
14057 }
14058 
14059 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14061  SCIP_VAR* var, /**< problem variable */
14062  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14063  )
14064 {
14065  assert(var != NULL);
14066  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14067 
14068  switch( SCIPvarGetStatus(var) )
14069  {
14071  if( var->data.original.transvar == NULL )
14072  return 0.0;
14073  else
14074  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14075 
14076  case SCIP_VARSTATUS_LOOSE:
14077  case SCIP_VARSTATUS_COLUMN:
14078  return SCIPhistoryGetPseudocostCount(var->history, dir);
14079 
14080  case SCIP_VARSTATUS_FIXED:
14081  return 0.0;
14082 
14084  if( var->data.aggregate.scalar > 0.0 )
14085  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14086  else
14088 
14090  return 0.0;
14091 
14094 
14095  default:
14096  SCIPerrorMessage("unknown variable status\n");
14097  SCIPABORT();
14098  return 0.0; /*lint !e527*/
14099  }
14100 }
14101 
14102 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14103  * only using the pseudo cost information of the current run
14104  */
14106  SCIP_VAR* var, /**< problem variable */
14107  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14108  )
14109 {
14110  assert(var != NULL);
14111  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14112 
14113  switch( SCIPvarGetStatus(var) )
14114  {
14116  if( var->data.original.transvar == NULL )
14117  return 0.0;
14118  else
14120 
14121  case SCIP_VARSTATUS_LOOSE:
14122  case SCIP_VARSTATUS_COLUMN:
14123  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14124 
14125  case SCIP_VARSTATUS_FIXED:
14126  return 0.0;
14127 
14129  if( var->data.aggregate.scalar > 0.0 )
14131  else
14133 
14135  return 0.0;
14136 
14139 
14140  default:
14141  SCIPerrorMessage("unknown variable status\n");
14142  SCIPABORT();
14143  return 0.0; /*lint !e527*/
14144  }
14145 }
14146 
14147 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14149  SCIP_VAR* var, /**< problem variable */
14150  SCIP_STAT* stat, /**< problem statistics */
14151  SCIP_SET* set, /**< global SCIP settings */
14152  SCIP_Real solval /**< solution value, e.g., LP solution value */
14153  )
14154 {
14155  SCIP_Real upscore;
14156  SCIP_Real downscore;
14157  SCIP_Real solvaldeltaup;
14158  SCIP_Real solvaldeltadown;
14159 
14160  /* LP root estimate only works for variables with fractional LP root solution */
14161  if( SCIPsetIsFeasIntegral(set, solval) )
14162  return 0.0;
14163 
14164  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14166  return 0.0;
14167 
14168  /* compute delta's to ceil and floor of root LP solution value */
14169  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14170  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14171 
14172  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14173  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14174 
14175  return MIN(upscore, downscore);
14176 }
14177 
14178 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14180  SCIP_VAR* var, /**< problem variable */
14181  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14182  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14183  )
14184 {
14185  assert(var != NULL);
14186  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14187 
14188  switch( SCIPvarGetStatus(var) )
14189  {
14191  if( var->data.original.transvar == NULL )
14192  return 0.0;
14193  else
14194  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14195 
14196  case SCIP_VARSTATUS_LOOSE:
14197  case SCIP_VARSTATUS_COLUMN:
14198  if( onlycurrentrun )
14200  else
14201  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14202 
14203  case SCIP_VARSTATUS_FIXED:
14204  return 0.0;
14205 
14207  if( var->data.aggregate.scalar > 0.0 )
14208  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14209  else
14210  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14211 
14213  return 0.0;
14214 
14216  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14217 
14218  default:
14219  SCIPerrorMessage("unknown variable status\n");
14220  SCIPABORT();
14221  return 0.0; /*lint !e527*/
14222  }
14223 }
14224 
14225 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14226  *
14227  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14228  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14229  * of 2 * clevel - 1.
14230  *
14231  * @return value of confidence bound for this variable
14232  */
14234  SCIP_VAR* var, /**< variable in question */
14235  SCIP_SET* set, /**< global SCIP settings */
14236  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14237  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14238  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14239  )
14240 {
14241  SCIP_Real confidencebound;
14242 
14243  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14244  if( SCIPsetIsFeasPositive(set, confidencebound) )
14245  {
14246  SCIP_Real count;
14247 
14248  if( onlycurrentrun )
14249  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14250  else
14251  count = SCIPvarGetPseudocostCount(var, dir);
14252  /* assertion is valid because variance is positive */
14253  assert(count >= 1.9);
14254 
14255  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14256  confidencebound = sqrt(confidencebound);
14257 
14258  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14259  * the number of pseudo cost evaluations of this variable in the respective direction. */
14260  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14261  }
14262  else
14263  confidencebound = 0.0;
14264 
14265  return confidencebound;
14266 }
14267 
14268 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14269  * Error is calculated at a specific confidence level
14270  */
14272  SCIP_VAR* var, /**< variable in question */
14273  SCIP_SET* set, /**< global SCIP settings */
14274  SCIP_STAT* stat, /**< problem statistics */
14275  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14276  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14277  )
14278 {
14279  SCIP_Real downsize;
14280  SCIP_Real upsize;
14281  SCIP_Real size;
14282  SCIP_Real relerrorup;
14283  SCIP_Real relerrordown;
14284  SCIP_Real relerror;
14285 
14286  /* check, if the pseudo cost score of the variable is reliable */
14289  size = MIN(downsize, upsize);
14290 
14291  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14292  if( size <= 1.9 )
14293  return FALSE;
14294 
14295  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14296  * confidence interval bound at confidence level of 95% for individual variable reliability.
14297  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14298  */
14299  if( downsize >= 1.9 )
14300  {
14301  SCIP_Real normval;
14302 
14303  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14304  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14305  normval = MAX(1.0, normval);
14306 
14307  relerrordown /= normval;
14308  }
14309  else
14310  relerrordown = 0.0;
14311 
14312  if( upsize >= 1.9 )
14313  {
14314  SCIP_Real normval;
14315 
14316  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14317  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14318  normval = MAX(1.0, normval);
14319  relerrorup /= normval;
14320  }
14321  else
14322  relerrorup = 0.0;
14323 
14324  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14325  relerror = MAX(relerrorup, relerrordown);
14326 
14327  return (relerror <= threshold);
14328 }
14329 
14330 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14331  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14332  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14333  * unknown location means of the underlying pseudo-cost distributions of x and y.
14334  *
14335  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14336  * better than x (despite the current information), meaning that y can be expected to yield branching
14337  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14338  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14339  * than y.
14340  *
14341  * @note The order of x and y matters for the one-sided hypothesis
14342  *
14343  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14344  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14345  *
14346  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14347  */
14349  SCIP_SET* set, /**< global SCIP settings */
14350  SCIP_STAT* stat, /**< problem statistics */
14351  SCIP_VAR* varx, /**< variable x */
14352  SCIP_Real fracx, /**< the fractionality of variable x */
14353  SCIP_VAR* vary, /**< variable y */
14354  SCIP_Real fracy, /**< the fractionality of variable y */
14355  SCIP_BRANCHDIR dir, /**< branching direction */
14356  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14357  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14358  )
14359 {
14360  SCIP_Real meanx;
14361  SCIP_Real meany;
14362  SCIP_Real variancex;
14363  SCIP_Real variancey;
14364  SCIP_Real countx;
14365  SCIP_Real county;
14366  SCIP_Real tresult;
14367  SCIP_Real realdirection;
14368 
14369  if( varx == vary )
14370  return FALSE;
14371 
14372  countx = SCIPvarGetPseudocostCount(varx, dir);
14373  county = SCIPvarGetPseudocostCount(vary, dir);
14374 
14375  /* if not at least 2 measurements were taken, return FALSE */
14376  if( countx <= 1.9 || county <= 1.9 )
14377  return FALSE;
14378 
14379  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14380 
14381  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14382  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14383 
14384  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14385  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14386 
14387  /* if there is no variance, the means are taken from a constant distribution */
14388  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14389  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14390 
14391  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14392 
14393  /* for the two-sided hypothesis, just take the absolute of t */
14394  if( !onesided )
14395  tresult = REALABS(tresult);
14396 
14397  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14398 }
14399 
14400 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14401  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14402  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14403  * of at least \p threshold.
14404  *
14405  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14406  * the estimated probability to exceed \p threshold is less than 25 %.
14407  *
14408  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14409  * of confidence.
14410  *
14411  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14412  * at the given confidence level \p clevel.
14413  */
14415  SCIP_SET* set, /**< global SCIP settings */
14416  SCIP_STAT* stat, /**< problem statistics */
14417  SCIP_VAR* var, /**< variable x */
14418  SCIP_Real frac, /**< the fractionality of variable x */
14419  SCIP_Real threshold, /**< the threshold to test against */
14420  SCIP_BRANCHDIR dir, /**< branching direction */
14421  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14422  )
14423 {
14424  SCIP_Real mean;
14425  SCIP_Real variance;
14426  SCIP_Real count;
14427  SCIP_Real realdirection;
14428  SCIP_Real probability;
14429  SCIP_Real problimit;
14430 
14431  count = SCIPvarGetPseudocostCount(var, dir);
14432 
14433  /* if not at least 2 measurements were taken, return FALSE */
14434  if( count <= 1.9 )
14435  return FALSE;
14436 
14437  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14438 
14439  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14440  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14441 
14442  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14443  if( SCIPsetIsFeasGE(set, mean, threshold) )
14444  return FALSE;
14445 
14446  /* if there is no variance, the means are taken from a constant distribution */
14447  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14448  return SCIPsetIsFeasLT(set, mean, threshold);
14449 
14450  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14451  probability = SCIPnormalCDF(mean, variance, threshold);
14452 
14453  /* determine a probability limit corresponding to the given confidence level */
14454  switch( clevel )
14455  {
14457  problimit = 0.75;
14458  break;
14460  problimit = 0.875;
14461  break;
14463  problimit = 0.9;
14464  break;
14466  problimit = 0.95;
14467  break;
14469  problimit = 0.975;
14470  break;
14471  default:
14472  problimit = -1;
14473  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14474  SCIPABORT();
14475  break;
14476  }
14477 
14478  return (probability >= problimit);
14479 }
14480 
14481 /** find the corresponding history entry if already existing, otherwise create new entry */
14482 static
14484  SCIP_VAR* var, /**< problem variable */
14485  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14486  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14487  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14488  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14489  )
14490 {
14491  assert(var != NULL);
14492  assert(blkmem != NULL);
14493  assert(set != NULL);
14494  assert(history != NULL);
14495 
14496  (*history) = NULL;
14497 
14498  if( var->valuehistory == NULL )
14499  {
14500  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14501  }
14502 
14503  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14504 
14505  return SCIP_OKAY;
14506 }
14507 
14508 /** check if value based history should be used */
14509 static
14511  SCIP_VAR* var, /**< problem variable */
14512  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14513  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14514  )
14515 {
14516  /* check if the domain value is unknown (not specific) */
14517  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14518  return FALSE;
14519 
14520  assert(set != NULL);
14521 
14522  /* check if value based history should be collected */
14523  if( !set->history_valuebased )
14524  return FALSE;
14525 
14526  /* value based history is not collected for binary variable since the standard history already contains all information */
14527  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14528  return FALSE;
14529 
14530  /* value based history is not collected for continuous variables */
14532  return FALSE;
14533 
14534  return TRUE;
14535 }
14536 
14537 /** increases VSIDS of the variable by the given weight */
14539  SCIP_VAR* var, /**< problem variable */
14540  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14541  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14542  SCIP_STAT* stat, /**< problem statistics */
14543  SCIP_BRANCHDIR dir, /**< branching direction */
14544  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14545  SCIP_Real weight /**< weight of this update in VSIDS */
14546  )
14547 {
14548  assert(var != NULL);
14549  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14550 
14551  /* check if history statistics should be collected for a variable */
14552  if( !stat->collectvarhistory )
14553  return SCIP_OKAY;
14554 
14555  if( SCIPsetIsZero(set, weight) )
14556  return SCIP_OKAY;
14557 
14558  switch( SCIPvarGetStatus(var) )
14559  {
14561  if( var->data.original.transvar == NULL )
14562  {
14563  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14564  return SCIP_INVALIDDATA;
14565  }
14566  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14567  return SCIP_OKAY;
14568 
14569  case SCIP_VARSTATUS_LOOSE:
14570  case SCIP_VARSTATUS_COLUMN:
14571  {
14572  SCIPhistoryIncVSIDS(var->history, dir, weight);
14573  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14574 
14575  if( useValuehistory(var, value, set) )
14576  {
14577  SCIP_HISTORY* history;
14578 
14579  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14580  assert(history != NULL);
14581 
14582  SCIPhistoryIncVSIDS(history, dir, weight);
14583  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14584  value, weight, SCIPhistoryGetVSIDS(history, dir));
14585  }
14586 
14587  return SCIP_OKAY;
14588  }
14589  case SCIP_VARSTATUS_FIXED:
14590  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14591  return SCIP_INVALIDDATA;
14592 
14594  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14595 
14596  if( var->data.aggregate.scalar > 0.0 )
14597  {
14598  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14599  }
14600  else
14601  {
14602  assert(var->data.aggregate.scalar < 0.0);
14603  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14604  }
14605  return SCIP_OKAY;
14606 
14608  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14609  return SCIP_INVALIDDATA;
14610 
14612  value = 1.0 - value;
14613 
14614  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14615  return SCIP_OKAY;
14616 
14617  default:
14618  SCIPerrorMessage("unknown variable status\n");
14619  return SCIP_INVALIDDATA;
14620  }
14621 }
14622 
14623 /** scales the VSIDS of the variable by the given scalar */
14625  SCIP_VAR* var, /**< problem variable */
14626  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14627  )
14628 {
14629  assert(var != NULL);
14630 
14631  switch( SCIPvarGetStatus(var) )
14632  {
14634  if( var->data.original.transvar == NULL )
14635  {
14636  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14637  return SCIP_INVALIDDATA;
14638  }
14640  return SCIP_OKAY;
14641 
14642  case SCIP_VARSTATUS_LOOSE:
14643  case SCIP_VARSTATUS_COLUMN:
14644  {
14645  SCIPhistoryScaleVSIDS(var->history, scalar);
14646  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14648 
14649  return SCIP_OKAY;
14650  }
14651  case SCIP_VARSTATUS_FIXED:
14652  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14653  return SCIP_INVALIDDATA;
14654 
14656  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14657  return SCIP_OKAY;
14658 
14660  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14661  return SCIP_INVALIDDATA;
14662 
14664  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14665  return SCIP_OKAY;
14666 
14667  default:
14668  SCIPerrorMessage("unknown variable status\n");
14669  return SCIP_INVALIDDATA;
14670  }
14671 }
14672 
14673 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14675  SCIP_VAR* var, /**< problem variable */
14676  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14677  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14678  SCIP_STAT* stat, /**< problem statistics */
14679  SCIP_BRANCHDIR dir, /**< branching direction */
14680  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14681  SCIP_Real length /**< length of the conflict */
14682  )
14683 {
14684  assert(var != NULL);
14685  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14686 
14687  /* check if history statistics should be collected for a variable */
14688  if( !stat->collectvarhistory )
14689  return SCIP_OKAY;
14690 
14691  switch( SCIPvarGetStatus(var) )
14692  {
14694  if( var->data.original.transvar == NULL )
14695  {
14696  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14697  return SCIP_INVALIDDATA;
14698  }
14699  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14700  return SCIP_OKAY;
14701 
14702  case SCIP_VARSTATUS_LOOSE:
14703  case SCIP_VARSTATUS_COLUMN:
14704  {
14705  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14706  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14707 
14708  if( useValuehistory(var, value, set) )
14709  {
14710  SCIP_HISTORY* history;
14711 
14712  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14713  assert(history != NULL);
14714 
14715  SCIPhistoryIncNActiveConflicts(history, dir, length);
14716  }
14717 
14718  return SCIP_OKAY;
14719  }
14720  case SCIP_VARSTATUS_FIXED:
14721  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14722  return SCIP_INVALIDDATA;
14723 
14725  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14726 
14727  if( var->data.aggregate.scalar > 0.0 )
14728  {
14729  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14730  }
14731  else
14732  {
14733  assert(var->data.aggregate.scalar < 0.0);
14734  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14735  }
14736  return SCIP_OKAY;
14737 
14739  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14740  return SCIP_INVALIDDATA;
14741 
14743  value = 1.0 - value;
14744 
14745  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14746  return SCIP_OKAY;
14747 
14748  default:
14749  SCIPerrorMessage("unknown variable status\n");
14750  return SCIP_INVALIDDATA;
14751  }
14752 }
14753 
14754 /** gets the number of active conflicts containing this variable in given direction */
14756  SCIP_VAR* var, /**< problem variable */
14757  SCIP_STAT* stat, /**< problem statistics */
14758  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14759  )
14760 {
14761  assert(var != NULL);
14762  assert(stat != NULL);
14763  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14764 
14765  switch( SCIPvarGetStatus(var) )
14766  {
14768  if( var->data.original.transvar == NULL )
14769  return 0;
14770  else
14771  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14772 
14773  case SCIP_VARSTATUS_LOOSE:
14774  case SCIP_VARSTATUS_COLUMN:
14775  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14776 
14777  case SCIP_VARSTATUS_FIXED:
14778  return 0;
14779 
14781  if( var->data.aggregate.scalar > 0.0 )
14782  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14783  else
14785 
14787  return 0;
14788 
14791 
14792  default:
14793  SCIPerrorMessage("unknown variable status\n");
14794  SCIPABORT();
14795  return 0; /*lint !e527*/
14796  }
14797 }
14798 
14799 /** gets the number of active conflicts containing this variable in given direction
14800  * in the current run
14801  */
14803  SCIP_VAR* var, /**< problem variable */
14804  SCIP_STAT* stat, /**< problem statistics */
14805  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14806  )
14807 {
14808  assert(var != NULL);
14809  assert(stat != NULL);
14810  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14811 
14812  switch( SCIPvarGetStatus(var) )
14813  {
14815  if( var->data.original.transvar == NULL )
14816  return 0;
14817  else
14819 
14820  case SCIP_VARSTATUS_LOOSE:
14821  case SCIP_VARSTATUS_COLUMN:
14822  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14823 
14824  case SCIP_VARSTATUS_FIXED:
14825  return 0;
14826 
14828  if( var->data.aggregate.scalar > 0.0 )
14829  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14830  else
14832 
14834  return 0;
14835 
14838 
14839  default:
14840  SCIPerrorMessage("unknown variable status\n");
14841  SCIPABORT();
14842  return 0; /*lint !e527*/
14843  }
14844 }
14845 
14846 /** gets the average conflict length in given direction due to branching on the variable */
14848  SCIP_VAR* var, /**< problem variable */
14849  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14850  )
14851 {
14852  assert(var != NULL);
14853  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14854 
14855  switch( SCIPvarGetStatus(var) )
14856  {
14858  if( var->data.original.transvar == NULL )
14859  return 0.0;
14860  else
14862 
14863  case SCIP_VARSTATUS_LOOSE:
14864  case SCIP_VARSTATUS_COLUMN:
14865  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14866  case SCIP_VARSTATUS_FIXED:
14867  return 0.0;
14868 
14870  if( var->data.aggregate.scalar > 0.0 )
14871  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14872  else
14874 
14876  return 0.0;
14877 
14880 
14881  default:
14882  SCIPerrorMessage("unknown variable status\n");
14883  SCIPABORT();
14884  return 0.0; /*lint !e527*/
14885  }
14886 }
14887 
14888 /** gets the average conflict length in given direction due to branching on the variable
14889  * in the current run
14890  */
14892  SCIP_VAR* var, /**< problem variable */
14893  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14894  )
14895 {
14896  assert(var != NULL);
14897  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14898 
14899  switch( SCIPvarGetStatus(var) )
14900  {
14902  if( var->data.original.transvar == NULL )
14903  return 0.0;
14904  else
14906 
14907  case SCIP_VARSTATUS_LOOSE:
14908  case SCIP_VARSTATUS_COLUMN:
14909  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14910 
14911  case SCIP_VARSTATUS_FIXED:
14912  return 0.0;
14913 
14915  if( var->data.aggregate.scalar > 0.0 )
14917  else
14919 
14921  return 0.0;
14922 
14925 
14926  default:
14927  SCIPerrorMessage("unknown variable status\n");
14928  SCIPABORT();
14929  return 0.0; /*lint !e527*/
14930  }
14931 }
14932 
14933 /** increases the number of branchings counter of the variable */
14935  SCIP_VAR* var, /**< problem variable */
14936  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14937  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14938  SCIP_STAT* stat, /**< problem statistics */
14939  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14940  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14941  int depth /**< depth at which the bound change took place */
14942  )
14943 {
14944  assert(var != NULL);
14945  assert(stat != NULL);
14946  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14947 
14948  /* check if history statistics should be collected for a variable */
14949  if( !stat->collectvarhistory )
14950  return SCIP_OKAY;
14951 
14952  switch( SCIPvarGetStatus(var) )
14953  {
14955  if( var->data.original.transvar == NULL )
14956  {
14957  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14958  return SCIP_INVALIDDATA;
14959  }
14960  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14961  return SCIP_OKAY;
14962 
14963  case SCIP_VARSTATUS_LOOSE:
14964  case SCIP_VARSTATUS_COLUMN:
14965  {
14966  SCIPhistoryIncNBranchings(var->history, dir, depth);
14967  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14968  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14969  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14970 
14971  if( useValuehistory(var, value, set) )
14972  {
14973  SCIP_HISTORY* history;
14974 
14975  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14976  assert(history != NULL);
14977 
14978  SCIPhistoryIncNBranchings(history, dir, depth);
14979  }
14980 
14981  return SCIP_OKAY;
14982  }
14983  case SCIP_VARSTATUS_FIXED:
14984  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14985  return SCIP_INVALIDDATA;
14986 
14988  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14989 
14990  if( var->data.aggregate.scalar > 0.0 )
14991  {
14992  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14993  }
14994  else
14995  {
14996  assert(var->data.aggregate.scalar < 0.0);
14997  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14998  }
14999  return SCIP_OKAY;
15000 
15002  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15003  return SCIP_INVALIDDATA;
15004 
15006  value = 1.0 - value;
15007 
15008  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15009  return SCIP_OKAY;
15010 
15011  default:
15012  SCIPerrorMessage("unknown variable status\n");
15013  return SCIP_INVALIDDATA;
15014  }
15015 }
15016 
15017 /** increases the inference sum of the variable by the given weight */
15019  SCIP_VAR* var, /**< problem variable */
15020  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15021  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15022  SCIP_STAT* stat, /**< problem statistics */
15023  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15024  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15025  SCIP_Real weight /**< weight of this update in inference score */
15026  )
15027 {
15028  assert(var != NULL);
15029  assert(stat != NULL);
15030  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15031 
15032  /* check if history statistics should be collected for a variable */
15033  if( !stat->collectvarhistory )
15034  return SCIP_OKAY;
15035 
15036  switch( SCIPvarGetStatus(var) )
15037  {
15039  if( var->data.original.transvar == NULL )
15040  {
15041  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15042  return SCIP_INVALIDDATA;
15043  }
15044  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15045  return SCIP_OKAY;
15046 
15047  case SCIP_VARSTATUS_LOOSE:
15048  case SCIP_VARSTATUS_COLUMN:
15049  {
15050  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15051  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15052  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15053  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15054 
15055  if( useValuehistory(var, value, set) )
15056  {
15057  SCIP_HISTORY* history;
15058 
15059  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15060  assert(history != NULL);
15061 
15062  SCIPhistoryIncInferenceSum(history, dir, weight);
15063  }
15064 
15065  return SCIP_OKAY;
15066  }
15067  case SCIP_VARSTATUS_FIXED:
15068  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15069  return SCIP_INVALIDDATA;
15070 
15072  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15073 
15074  if( var->data.aggregate.scalar > 0.0 )
15075  {
15076  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15077  }
15078  else
15079  {
15080  assert(var->data.aggregate.scalar < 0.0);
15081  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15082  }
15083  return SCIP_OKAY;
15084 
15086  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15087  return SCIP_INVALIDDATA;
15088 
15090  value = 1.0 - value;
15091 
15092  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15093  return SCIP_OKAY;
15094 
15095  default:
15096  SCIPerrorMessage("unknown variable status\n");
15097  return SCIP_INVALIDDATA;
15098  }
15099 }
15100 
15101 /** increases the cutoff sum of the variable by the given weight */
15103  SCIP_VAR* var, /**< problem variable */
15104  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15105  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15106  SCIP_STAT* stat, /**< problem statistics */
15107  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15108  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15109  SCIP_Real weight /**< weight of this update in cutoff score */
15110  )
15111 {
15112  assert(var != NULL);
15113  assert(stat != NULL);
15114  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15115 
15116  /* check if history statistics should be collected for a variable */
15117  if( !stat->collectvarhistory )
15118  return SCIP_OKAY;
15119 
15120  switch( SCIPvarGetStatus(var) )
15121  {
15123  if( var->data.original.transvar == NULL )
15124  {
15125  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15126  return SCIP_INVALIDDATA;
15127  }
15128  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15129  return SCIP_OKAY;
15130 
15131  case SCIP_VARSTATUS_LOOSE:
15132  case SCIP_VARSTATUS_COLUMN:
15133  {
15134  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15135  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15136  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15137  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15138 
15139  if( useValuehistory(var, value, set) )
15140  {
15141  SCIP_HISTORY* history;
15142 
15143  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15144  assert(history != NULL);
15145 
15146  SCIPhistoryIncCutoffSum(history, dir, weight);
15147  }
15148 
15149  return SCIP_OKAY;
15150  }
15151  case SCIP_VARSTATUS_FIXED:
15152  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15153  return SCIP_INVALIDDATA;
15154 
15156  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15157 
15158  if( var->data.aggregate.scalar > 0.0 )
15159  {
15160  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15161  }
15162  else
15163  {
15164  assert(var->data.aggregate.scalar < 0.0);
15165  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15166  }
15167  return SCIP_OKAY;
15168 
15170  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15171  return SCIP_INVALIDDATA;
15172 
15174  value = 1.0 - value;
15175 
15176  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15177  return SCIP_OKAY;
15178 
15179  default:
15180  SCIPerrorMessage("unknown variable status\n");
15181  return SCIP_INVALIDDATA;
15182  }
15183 }
15184 
15185 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15187  SCIP_VAR* var, /**< problem variable */
15188  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15189  )
15190 {
15191  assert(var != NULL);
15192  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15193 
15194  switch( SCIPvarGetStatus(var) )
15195  {
15197  if( var->data.original.transvar == NULL )
15198  return 0;
15199  else
15200  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15201 
15202  case SCIP_VARSTATUS_LOOSE:
15203  case SCIP_VARSTATUS_COLUMN:
15204  return SCIPhistoryGetNBranchings(var->history, dir);
15205 
15206  case SCIP_VARSTATUS_FIXED:
15207  return 0;
15208 
15210  if( var->data.aggregate.scalar > 0.0 )
15211  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15212  else
15214 
15216  return 0;
15217 
15220 
15221  default:
15222  SCIPerrorMessage("unknown variable status\n");
15223  SCIPABORT();
15224  return 0; /*lint !e527*/
15225  }
15226 }
15227 
15228 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15229  * in the current run
15230  */
15232  SCIP_VAR* var, /**< problem variable */
15233  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15234  )
15235 {
15236  assert(var != NULL);
15237  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15238 
15239  switch( SCIPvarGetStatus(var) )
15240  {
15242  if( var->data.original.transvar == NULL )
15243  return 0;
15244  else
15246 
15247  case SCIP_VARSTATUS_LOOSE:
15248  case SCIP_VARSTATUS_COLUMN:
15249  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15250 
15251  case SCIP_VARSTATUS_FIXED:
15252  return 0;
15253 
15255  if( var->data.aggregate.scalar > 0.0 )
15257  else
15259 
15261  return 0;
15262 
15265 
15266  default:
15267  SCIPerrorMessage("unknown variable status\n");
15268  SCIPABORT();
15269  return 0; /*lint !e527*/
15270  }
15271 }
15272 
15273 /** returns the average depth of bound changes in given direction due to branching on the variable */
15275  SCIP_VAR* var, /**< problem variable */
15276  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15277  )
15278 {
15279  assert(var != NULL);
15280  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15281 
15282  switch( SCIPvarGetStatus(var) )
15283  {
15285  if( var->data.original.transvar == NULL )
15286  return 0.0;
15287  else
15288  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15289 
15290  case SCIP_VARSTATUS_LOOSE:
15291  case SCIP_VARSTATUS_COLUMN:
15292  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15293 
15294  case SCIP_VARSTATUS_FIXED:
15295  return 0.0;
15296 
15298  if( var->data.aggregate.scalar > 0.0 )
15299  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15300  else
15302 
15304  return 0.0;
15305 
15308 
15309  default:
15310  SCIPerrorMessage("unknown variable status\n");
15311  SCIPABORT();
15312  return 0.0; /*lint !e527*/
15313  }
15314 }
15315 
15316 /** returns the average depth of bound changes in given direction due to branching on the variable
15317  * in the current run
15318  */
15320  SCIP_VAR* var, /**< problem variable */
15321  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15322  )
15323 {
15324  assert(var != NULL);
15325  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15326 
15327  switch( SCIPvarGetStatus(var) )
15328  {
15330  if( var->data.original.transvar == NULL )
15331  return 0.0;
15332  else
15334 
15335  case SCIP_VARSTATUS_LOOSE:
15336  case SCIP_VARSTATUS_COLUMN:
15337  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15338 
15339  case SCIP_VARSTATUS_FIXED:
15340  return 0.0;
15341 
15343  if( var->data.aggregate.scalar > 0.0 )
15345  else
15348 
15350  return 0.0;
15351 
15354  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15355 
15356  default:
15357  SCIPerrorMessage("unknown variable status\n");
15358  SCIPABORT();
15359  return 0.0; /*lint !e527*/
15360  }
15361 }
15362 
15363 /** returns the variable's VSIDS score */
15365  SCIP_VAR* var, /**< problem variable */
15366  SCIP_STAT* stat, /**< problem statistics */
15367  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15368  )
15369 {
15370  assert(var != NULL);
15371  assert(stat != NULL);
15372  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15373 
15375  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15376 
15377  switch( SCIPvarGetStatus(var) )
15378  {
15380  if( var->data.original.transvar == NULL )
15381  return 0.0;
15382  else
15383  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15384 
15385  case SCIP_VARSTATUS_LOOSE:
15386  case SCIP_VARSTATUS_COLUMN:
15387  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15388  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15389 
15390  case SCIP_VARSTATUS_FIXED:
15391  return 0.0;
15392 
15394  if( var->data.aggregate.scalar > 0.0 )
15395  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15396  else
15397  /* coverity[overrun-local] */
15398  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15399 
15401  return 0.0;
15402 
15404  /* coverity[overrun-local] */
15405  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15406 
15407  default:
15408  SCIPerrorMessage("unknown variable status\n");
15409  SCIPABORT();
15410  return 0.0; /*lint !e527*/
15411  }
15412 }
15413 
15414 /** returns the variable's VSIDS score only using conflicts of the current run */
15416  SCIP_VAR* var, /**< problem variable */
15417  SCIP_STAT* stat, /**< problem statistics */
15418  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15419  )
15420 {
15421  assert(var != NULL);
15422  assert(stat != NULL);
15423  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15424 
15425  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15426  {
15427  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15428  return SCIP_INVALID;
15429  }
15430 
15431  switch( SCIPvarGetStatus(var) )
15432  {
15434  if( var->data.original.transvar == NULL )
15435  return 0.0;
15436  else
15437  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15438 
15439  case SCIP_VARSTATUS_LOOSE:
15440  case SCIP_VARSTATUS_COLUMN:
15441  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15442 
15443  case SCIP_VARSTATUS_FIXED:
15444  return 0.0;
15445 
15447  if( var->data.aggregate.scalar > 0.0 )
15448  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15449  else
15451 
15453  return 0.0;
15454 
15457 
15458  default:
15459  SCIPerrorMessage("unknown variable status\n");
15460  SCIPABORT();
15461  return 0.0; /*lint !e527*/
15462  }
15463 }
15464 
15465 /** returns the number of inferences branching on this variable in given direction triggered */
15467  SCIP_VAR* var, /**< problem variable */
15468  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15469  )
15470 {
15471  assert(var != NULL);
15472  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15473 
15474  switch( SCIPvarGetStatus(var) )
15475  {
15477  if( var->data.original.transvar == NULL )
15478  return 0.0;
15479  else
15480  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15481 
15482  case SCIP_VARSTATUS_LOOSE:
15483  case SCIP_VARSTATUS_COLUMN:
15484  return SCIPhistoryGetInferenceSum(var->history, dir);
15485 
15486  case SCIP_VARSTATUS_FIXED:
15487  return 0.0;
15488 
15490  if( var->data.aggregate.scalar > 0.0 )
15491  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15492  else
15494 
15496  return 0.0;
15497 
15500 
15501  default:
15502  SCIPerrorMessage("unknown variable status\n");
15503  SCIPABORT();
15504  return 0.0; /*lint !e527*/
15505  }
15506 }
15507 
15508 /** returns the number of inferences branching on this variable in given direction triggered
15509  * in the current run
15510  */
15512  SCIP_VAR* var, /**< problem variable */
15513  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15514  )
15515 {
15516  assert(var != NULL);
15517  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15518 
15519  switch( SCIPvarGetStatus(var) )
15520  {
15522  if( var->data.original.transvar == NULL )
15523  return 0.0;
15524  else
15526 
15527  case SCIP_VARSTATUS_LOOSE:
15528  case SCIP_VARSTATUS_COLUMN:
15529  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15530 
15531  case SCIP_VARSTATUS_FIXED:
15532  return 0.0;
15533 
15535  if( var->data.aggregate.scalar > 0.0 )
15537  else
15539 
15541  return 0.0;
15542 
15545 
15546  default:
15547  SCIPerrorMessage("unknown variable status\n");
15548  SCIPABORT();
15549  return 0.0; /*lint !e527*/
15550  }
15551 }
15552 
15553 /** returns the average number of inferences found after branching on the variable in given direction */
15555  SCIP_VAR* var, /**< problem variable */
15556  SCIP_STAT* stat, /**< problem statistics */
15557  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15558  )
15559 {
15560  assert(var != NULL);
15561  assert(stat != NULL);
15562  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15563 
15564  switch( SCIPvarGetStatus(var) )
15565  {
15567  if( var->data.original.transvar == NULL )
15568  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15569  else
15570  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15571 
15572  case SCIP_VARSTATUS_LOOSE:
15573  case SCIP_VARSTATUS_COLUMN:
15574  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15575  return SCIPhistoryGetAvgInferences(var->history, dir);
15576  else
15577  {
15578  int nimpls;
15579  int ncliques;
15580 
15581  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15582  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15583  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15584  }
15585 
15586  case SCIP_VARSTATUS_FIXED:
15587  return 0.0;
15588 
15590  if( var->data.aggregate.scalar > 0.0 )
15591  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15592  else
15594 
15596  return 0.0;
15597 
15599  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15600 
15601  default:
15602  SCIPerrorMessage("unknown variable status\n");
15603  SCIPABORT();
15604  return 0.0; /*lint !e527*/
15605  }
15606 }
15607 
15608 /** returns the average number of inferences found after branching on the variable in given direction
15609  * in the current run
15610  */
15612  SCIP_VAR* var, /**< problem variable */
15613  SCIP_STAT* stat, /**< problem statistics */
15614  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15615  )
15616 {
15617  assert(var != NULL);
15618  assert(stat != NULL);
15619  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15620 
15621  switch( SCIPvarGetStatus(var) )
15622  {
15624  if( var->data.original.transvar == NULL )
15625  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15626  else
15627  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15628 
15629  case SCIP_VARSTATUS_LOOSE:
15630  case SCIP_VARSTATUS_COLUMN:
15631  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15632  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15633  else
15634  {
15635  int nimpls;
15636  int ncliques;
15637 
15638  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15639  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15640  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15641  }
15642 
15643  case SCIP_VARSTATUS_FIXED:
15644  return 0.0;
15645 
15647  if( var->data.aggregate.scalar > 0.0 )
15648  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15649  else
15651 
15653  return 0.0;
15654 
15657 
15658  default:
15659  SCIPerrorMessage("unknown variable status\n");
15660  SCIPABORT();
15661  return 0.0; /*lint !e527*/
15662  }
15663 }
15664 
15665 /** returns the number of cutoffs branching on this variable in given direction produced */
15667  SCIP_VAR* var, /**< problem variable */
15668  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15669  )
15670 {
15671  assert(var != NULL);
15672  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15673 
15674  switch( SCIPvarGetStatus(var) )
15675  {
15677  if( var->data.original.transvar == NULL )
15678  return 0;
15679  else
15680  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15681 
15682  case SCIP_VARSTATUS_LOOSE:
15683  case SCIP_VARSTATUS_COLUMN:
15684  return SCIPhistoryGetCutoffSum(var->history, dir);
15685 
15686  case SCIP_VARSTATUS_FIXED:
15687  return 0;
15688 
15690  if( var->data.aggregate.scalar > 0.0 )
15691  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15692  else
15694 
15696  return 0;
15697 
15700 
15701  default:
15702  SCIPerrorMessage("unknown variable status\n");
15703  SCIPABORT();
15704  return 0; /*lint !e527*/
15705  }
15706 }
15707 
15708 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15710  SCIP_VAR* var, /**< problem variable */
15711  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15712  )
15713 {
15714  assert(var != NULL);
15715  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15716 
15717  switch( SCIPvarGetStatus(var) )
15718  {
15720  if( var->data.original.transvar == NULL )
15721  return 0;
15722  else
15724 
15725  case SCIP_VARSTATUS_LOOSE:
15726  case SCIP_VARSTATUS_COLUMN:
15727  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15728 
15729  case SCIP_VARSTATUS_FIXED:
15730  return 0;
15731 
15733  if( var->data.aggregate.scalar > 0.0 )
15734  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15735  else
15737 
15739  return 0;
15740 
15743 
15744  default:
15745  SCIPerrorMessage("unknown variable status\n");
15746  SCIPABORT();
15747  return 0; /*lint !e527*/
15748  }
15749 }
15750 
15751 /** returns the average number of cutoffs found after branching on the variable in given direction */
15753  SCIP_VAR* var, /**< problem variable */
15754  SCIP_STAT* stat, /**< problem statistics */
15755  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15756  )
15757 {
15758  assert(var != NULL);
15759  assert(stat != NULL);
15760  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15761 
15762  switch( SCIPvarGetStatus(var) )
15763  {
15765  if( var->data.original.transvar == NULL )
15766  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15767  else
15768  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15769 
15770  case SCIP_VARSTATUS_LOOSE:
15771  case SCIP_VARSTATUS_COLUMN:
15772  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15773  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15774  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15775 
15776  case SCIP_VARSTATUS_FIXED:
15777  return 0.0;
15778 
15780  if( var->data.aggregate.scalar > 0.0 )
15781  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15782  else
15783  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15784 
15786  return 0.0;
15787 
15789  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15790 
15791  default:
15792  SCIPerrorMessage("unknown variable status\n");
15793  SCIPABORT();
15794  return 0.0; /*lint !e527*/
15795  }
15796 }
15797 
15798 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15800  SCIP_VAR* var, /**< problem variable */
15801  SCIP_STAT* stat, /**< problem statistics */
15802  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15803  )
15804 {
15805  assert(var != NULL);
15806  assert(stat != NULL);
15807  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15808 
15809  switch( SCIPvarGetStatus(var) )
15810  {
15812  if( var->data.original.transvar == NULL )
15813  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15814  else
15815  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15816 
15817  case SCIP_VARSTATUS_LOOSE:
15818  case SCIP_VARSTATUS_COLUMN:
15819  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15822 
15823  case SCIP_VARSTATUS_FIXED:
15824  return 0.0;
15825 
15827  if( var->data.aggregate.scalar > 0.0 )
15828  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15829  else
15831 
15833  return 0.0;
15834 
15837 
15838  default:
15839  SCIPerrorMessage("unknown variable status\n");
15840  SCIPABORT();
15841  return 0.0; /*lint !e527*/
15842  }
15843 }
15844 
15845 
15846 
15847 
15848 /*
15849  * information methods for bound changes
15850  */
15851 
15852 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15854  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15855  BMS_BLKMEM* blkmem, /**< block memory */
15856  SCIP_VAR* var, /**< active variable that changed the bounds */
15857  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15858  SCIP_Real oldbound, /**< old value for bound */
15859  SCIP_Real newbound /**< new value for bound */
15860  )
15861 {
15862  assert(bdchginfo != NULL);
15863 
15864  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15865  (*bdchginfo)->oldbound = oldbound;
15866  (*bdchginfo)->newbound = newbound;
15867  (*bdchginfo)->var = var;
15868  (*bdchginfo)->inferencedata.var = var;
15869  (*bdchginfo)->inferencedata.reason.prop = NULL;
15870  (*bdchginfo)->inferencedata.info = 0;
15871  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15872  (*bdchginfo)->bdchgidx.pos = -1;
15873  (*bdchginfo)->pos = 0;
15874  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15875  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15876  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15877  (*bdchginfo)->redundant = FALSE;
15878 
15879  return SCIP_OKAY;
15880 }
15881 
15882 /** frees a bound change information object */
15883 void SCIPbdchginfoFree(
15884  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15885  BMS_BLKMEM* blkmem /**< block memory */
15886  )
15887 {
15888  assert(bdchginfo != NULL);
15889 
15890  BMSfreeBlockMemory(blkmem, bdchginfo);
15891 }
15892 
15893 /** returns the bound change information for the last lower bound change on given active problem variable before or
15894  * after the bound change with the given index was applied;
15895  * returns NULL, if no change to the lower bound was applied up to this point of time
15896  */
15898  SCIP_VAR* var, /**< active problem variable */
15899  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15900  SCIP_Bool after /**< should the bound change with given index be included? */
15901  )
15902 {
15903  int i;
15904 
15905  assert(var != NULL);
15906  assert(SCIPvarIsActive(var));
15907 
15908  /* search the correct bound change information for the given bound change index */
15909  if( after )
15910  {
15911  for( i = var->nlbchginfos-1; i >= 0; --i )
15912  {
15913  assert(var->lbchginfos[i].var == var);
15915  assert(var->lbchginfos[i].pos == i);
15916 
15917  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15918  if( var->lbchginfos[i].redundant )
15919  return NULL;
15920  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15921 
15922  /* if we reached the bound change index, return the current bound change info */
15923  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15924  return &var->lbchginfos[i];
15925  }
15926  }
15927  else
15928  {
15929  for( i = var->nlbchginfos-1; i >= 0; --i )
15930  {
15931  assert(var->lbchginfos[i].var == var);
15933  assert(var->lbchginfos[i].pos == i);
15934 
15935  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15936  if( var->lbchginfos[i].redundant )
15937  return NULL;
15938  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15939 
15940  /* if we reached the bound change index, return the current bound change info */
15941  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15942  return &var->lbchginfos[i];
15943  }
15944  }
15945 
15946  return NULL;
15947 }
15948 
15949 /** returns the bound change information for the last upper bound change on given active problem variable before or
15950  * after the bound change with the given index was applied;
15951  * returns NULL, if no change to the upper bound was applied up to this point of time
15952  */
15954  SCIP_VAR* var, /**< active problem variable */
15955  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15956  SCIP_Bool after /**< should the bound change with given index be included? */
15957  )
15958 {
15959  int i;
15960 
15961  assert(var != NULL);
15962  assert(SCIPvarIsActive(var));
15963 
15964  /* search the correct bound change information for the given bound change index */
15965  if( after )
15966  {
15967  for( i = var->nubchginfos-1; i >= 0; --i )
15968  {
15969  assert(var->ubchginfos[i].var == var);
15971  assert(var->ubchginfos[i].pos == i);
15972 
15973  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15974  if( var->ubchginfos[i].redundant )
15975  return NULL;
15976  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15977 
15978  /* if we reached the bound change index, return the current bound change info */
15979  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15980  return &var->ubchginfos[i];
15981  }
15982  }
15983  else
15984  {
15985  for( i = var->nubchginfos-1; i >= 0; --i )
15986  {
15987  assert(var->ubchginfos[i].var == var);
15989  assert(var->ubchginfos[i].pos == i);
15990 
15991  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15992  if( var->ubchginfos[i].redundant )
15993  return NULL;
15994  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15995 
15996  /* if we reached the bound change index, return the current bound change info */
15997  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15998  return &var->ubchginfos[i];
15999  }
16000  }
16001 
16002  return NULL;
16003 }
16004 
16005 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16006  * before or after the bound change with the given index was applied;
16007  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16008  */
16010  SCIP_VAR* var, /**< active problem variable */
16011  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16012  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16013  SCIP_Bool after /**< should the bound change with given index be included? */
16014  )
16015 {
16016  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16017  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16018  else
16019  {
16020  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16021  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16022  }
16023 }
16024 
16025 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16026  * was applied
16027  *
16028  * @deprecated Please use SCIPgetVarLbAtIndex()
16029  */
16031  SCIP_VAR* var, /**< problem variable */
16032  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16033  SCIP_Bool after /**< should the bound change with given index be included? */
16034  )
16035 {
16036  SCIP_VARSTATUS varstatus;
16037  assert(var != NULL);
16038 
16039  varstatus = SCIPvarGetStatus(var);
16040 
16041  /* get bounds of attached variables */
16042  switch( varstatus )
16043  {
16045  assert(var->data.original.transvar != NULL);
16046  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16047 
16048  case SCIP_VARSTATUS_LOOSE:
16049  case SCIP_VARSTATUS_COLUMN:
16050  if( bdchgidx == NULL )
16051  return SCIPvarGetLbLocal(var);
16052  else
16053  {
16054  SCIP_BDCHGINFO* bdchginfo;
16055 
16056  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16057  if( bdchginfo != NULL )
16058  return SCIPbdchginfoGetNewbound(bdchginfo);
16059  else
16060  return var->glbdom.lb;
16061  }
16062  case SCIP_VARSTATUS_FIXED:
16063  return var->glbdom.lb;
16064 
16065  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16066  assert(var->data.aggregate.var != NULL);
16067  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16068  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16069  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16070  * (or is called by) a public interface method; instead, we only assert that values are finite
16071  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16072  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16073  */
16074  if( var->data.aggregate.scalar > 0.0 )
16075  {
16076  /* a > 0 -> get lower bound of y */
16077  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16078  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16079  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16080  + var->data.aggregate.constant;
16081  }
16082  else if( var->data.aggregate.scalar < 0.0 )
16083  {
16084  /* a < 0 -> get upper bound of y */
16085  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16086  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16087  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16088  + var->data.aggregate.constant;
16089  }
16090  else
16091  {
16092  SCIPerrorMessage("scalar is zero in aggregation\n");
16093  SCIPABORT();
16094  return SCIP_INVALID; /*lint !e527*/
16095  }
16096 
16098  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16099  if ( var->data.multaggr.nvars == 1 )
16100  {
16101  assert(var->data.multaggr.vars != NULL);
16102  assert(var->data.multaggr.scalars != NULL);
16103  assert(var->data.multaggr.vars[0] != NULL);
16104 
16105  if( var->data.multaggr.scalars[0] > 0.0 )
16106  {
16107  /* a > 0 -> get lower bound of y */
16108  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16109  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16110  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16111  + var->data.multaggr.constant;
16112  }
16113  else if( var->data.multaggr.scalars[0] < 0.0 )
16114  {
16115  /* a < 0 -> get upper bound of y */
16116  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16117  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16118  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16119  + var->data.multaggr.constant;
16120  }
16121  else
16122  {
16123  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16124  SCIPABORT();
16125  return SCIP_INVALID; /*lint !e527*/
16126  }
16127  }
16128  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16129  SCIPABORT();
16130  return SCIP_INVALID; /*lint !e527*/
16131 
16132  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16133  assert(var->negatedvar != NULL);
16135  assert(var->negatedvar->negatedvar == var);
16136  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16137  default:
16138  SCIPerrorMessage("unknown variable status\n");
16139  SCIPABORT();
16140  return SCIP_INVALID; /*lint !e527*/
16141  }
16142 }
16143 
16144 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16145  * was applied
16146  *
16147  * @deprecated Please use SCIPgetVarUbAtIndex()
16148  */
16150  SCIP_VAR* var, /**< problem variable */
16151  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16152  SCIP_Bool after /**< should the bound change with given index be included? */
16153  )
16154 {
16155  SCIP_VARSTATUS varstatus;
16156  assert(var != NULL);
16157 
16158  varstatus = SCIPvarGetStatus(var);
16159 
16160  /* get bounds of attached variables */
16161  switch( varstatus )
16162  {
16164  assert(var->data.original.transvar != NULL);
16165  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16166 
16167  case SCIP_VARSTATUS_COLUMN:
16168  case SCIP_VARSTATUS_LOOSE:
16169  if( bdchgidx == NULL )
16170  return SCIPvarGetUbLocal(var);
16171  else
16172  {
16173  SCIP_BDCHGINFO* bdchginfo;
16174 
16175  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16176  if( bdchginfo != NULL )
16177  return SCIPbdchginfoGetNewbound(bdchginfo);
16178  else
16179  return var->glbdom.ub;
16180  }
16181 
16182  case SCIP_VARSTATUS_FIXED:
16183  return var->glbdom.ub;
16184 
16185  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16186  assert(var->data.aggregate.var != NULL);
16187  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16188  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16189  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16190  * (or is called by) a public interface method; instead, we only assert that values are finite
16191  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16192  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16193  */
16194  if( var->data.aggregate.scalar > 0.0 )
16195  {
16196  /* a > 0 -> get lower bound of y */
16197  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16198  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16199  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16200  + var->data.aggregate.constant;
16201  }
16202  else if( var->data.aggregate.scalar < 0.0 )
16203  {
16204  /* a < 0 -> get upper bound of y */
16205  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16206  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16207  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16208  + var->data.aggregate.constant;
16209  }
16210  else
16211  {
16212  SCIPerrorMessage("scalar is zero in aggregation\n");
16213  SCIPABORT();
16214  return SCIP_INVALID; /*lint !e527*/
16215  }
16216 
16218  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16219  if ( var->data.multaggr.nvars == 1 )
16220  {
16221  assert(var->data.multaggr.vars != NULL);
16222  assert(var->data.multaggr.scalars != NULL);
16223  assert(var->data.multaggr.vars[0] != NULL);
16224 
16225  if( var->data.multaggr.scalars[0] > 0.0 )
16226  {
16227  /* a > 0 -> get lower bound of y */
16228  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16229  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16230  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16231  + var->data.multaggr.constant;
16232  }
16233  else if( var->data.multaggr.scalars[0] < 0.0 )
16234  {
16235  /* a < 0 -> get upper bound of y */
16236  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16237  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16238  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16239  + var->data.multaggr.constant;
16240  }
16241  else
16242  {
16243  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16244  SCIPABORT();
16245  return SCIP_INVALID; /*lint !e527*/
16246  }
16247  }
16248  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16249  SCIPABORT();
16250  return SCIP_INVALID; /*lint !e527*/
16251 
16252  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16253  assert(var->negatedvar != NULL);
16255  assert(var->negatedvar->negatedvar == var);
16256  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16257 
16258  default:
16259  SCIPerrorMessage("unknown variable status\n");
16260  SCIPABORT();
16261  return SCIP_INVALID; /*lint !e527*/
16262  }
16263 }
16264 
16265 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16266  * was applied
16267  *
16268  * @deprecated Please use SCIPgetVarBdAtIndex()
16269  */
16271  SCIP_VAR* var, /**< problem variable */
16272  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16273  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16274  SCIP_Bool after /**< should the bound change with given index be included? */
16275  )
16276 {
16277  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16278  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16279  else
16280  {
16281  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16282  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16283  }
16284 }
16285 
16286 /** returns whether the binary variable was fixed at the time given by the bound change index
16287  *
16288  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16289  */
16291  SCIP_VAR* var, /**< problem variable */
16292  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16293  SCIP_Bool after /**< should the bound change with given index be included? */
16294  )
16295 {
16296  assert(var != NULL);
16297  assert(SCIPvarIsBinary(var));
16298 
16299  /* check the current bounds first in order to decide at which bound change information we have to look
16300  * (which is expensive because we have to follow the aggregation tree to the active variable)
16301  */
16302  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16303  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16304 }
16305 
16306 /** bound change index representing the initial time before any bound changes took place */
16307 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16309 /** bound change index representing the presolving stage */
16310 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16312 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16314  SCIP_VAR* var /**< problem variable */
16315  )
16316 {
16317  SCIP_BDCHGIDX* lbchgidx;
16318  SCIP_BDCHGIDX* ubchgidx;
16319 
16320  assert(var != NULL);
16321 
16322  var = SCIPvarGetProbvar(var);
16323 
16324  /* check, if variable is original without transformed variable */
16325  if( var == NULL )
16326  return &initbdchgidx;
16327 
16328  /* check, if variable was fixed in presolving */
16329  if( !SCIPvarIsActive(var) )
16330  return &presolvebdchgidx;
16331 
16333 
16334  /* get depths of last bound change information for the lower and upper bound */
16335  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16336  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16337  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16338  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16339 
16340  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16341  return ubchgidx;
16342  else
16343  return lbchgidx;
16344 }
16345 
16346 /** returns the last depth level, at which the bounds of the given variable were tightened;
16347  * returns -2, if the variable's bounds are still the global bounds
16348  * returns -1, if the variable was fixed in presolving
16349  */
16351  SCIP_VAR* var /**< problem variable */
16352  )
16353 {
16354  SCIP_BDCHGIDX* bdchgidx;
16355 
16356  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16357  assert(bdchgidx != NULL);
16358 
16359  return bdchgidx->depth;
16360 }
16361 
16362 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16363  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16364  */
16366  SCIP_VAR* var, /**< problem variable */
16367  SCIP_SET* set, /**< global SCIP settings */
16368  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16369  SCIP_Real bound /**< conflicting bound */
16370  )
16371 {
16372  int i;
16373 
16374  assert(var != NULL);
16375  assert(set != NULL);
16376  assert(var->scip == set->scip);
16377 
16378  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16379  {
16380  /* check if the bound is in conflict with the current local bounds */
16381  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16382  return -1;
16383 
16384  /* check if the bound is in conflict with the global bound */
16385  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16386  return 0;
16387 
16388  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16389  assert(var->nubchginfos > 0);
16390  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16391 
16392  /* search for the first conflicting bound change */
16393  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16394  {
16395  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16397  }
16398  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16399  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16400 
16401  /* return the depth at which the first conflicting bound change took place */
16402  return var->ubchginfos[i].bdchgidx.depth;
16403  }
16404  else
16405  {
16406  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16407 
16408  /* check if the bound is in conflict with the current local bounds */
16409  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16410  return -1;
16411 
16412  /* check if the bound is in conflict with the global bound */
16413  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16414  return 0;
16415 
16416  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16417  assert(var->nlbchginfos > 0);
16418  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16419 
16420  /* search for the first conflicting bound change */
16421  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16422  {
16423  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16425  }
16426  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16427  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16428 
16429  /* return the depth at which the first conflicting bound change took place */
16430  return var->lbchginfos[i].bdchgidx.depth;
16431  }
16432 }
16433 
16434 /** returns whether the first binary variable was fixed earlier than the second one;
16435  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16436  * second one is not fixed
16437  */
16439  SCIP_VAR* var1, /**< first binary variable */
16440  SCIP_VAR* var2 /**< second binary variable */
16441  )
16442 {
16443  SCIP_BDCHGIDX* bdchgidx1;
16444  SCIP_BDCHGIDX* bdchgidx2;
16445 
16446  assert(var1 != NULL);
16447  assert(var2 != NULL);
16448  assert(SCIPvarIsBinary(var1));
16449  assert(SCIPvarIsBinary(var2));
16450 
16451  var1 = SCIPvarGetProbvar(var1);
16452  var2 = SCIPvarGetProbvar(var2);
16453  assert(var1 != NULL);
16454  assert(var2 != NULL);
16455 
16456  /* check, if variables are globally fixed */
16457  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16458  return FALSE;
16459  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16460  return TRUE;
16461 
16464  assert(SCIPvarIsBinary(var1));
16465  assert(SCIPvarIsBinary(var2));
16466  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16467  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16468  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16469  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16470  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16471  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16472 
16473  if( var1->nlbchginfos == 1 )
16474  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16475  else if( var1->nubchginfos == 1 )
16476  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16477  else
16478  bdchgidx1 = NULL;
16479 
16480  if( var2->nlbchginfos == 1 )
16481  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16482  else if( var2->nubchginfos == 1 )
16483  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16484  else
16485  bdchgidx2 = NULL;
16486 
16487  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16488 }
16489 
16490 
16491 
16492 /*
16493  * Hash functions
16494  */
16495 
16496 /** gets the key (i.e. the name) of the given variable */
16497 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16498 { /*lint --e{715}*/
16499  SCIP_VAR* var = (SCIP_VAR*)elem;
16500 
16501  assert(var != NULL);
16502  return var->name;
16503 }
16504 
16505 
16506 
16507 
16508 /*
16509  * simple functions implemented as defines
16510  */
16511 
16512 /* In debug mode, the following methods are implemented as function calls to ensure
16513  * type validity.
16514  * In optimized mode, the methods are implemented as defines to improve performance.
16515  * However, we want to have them in the library anyways, so we have to undef the defines.
16516  */
16517 
16518 #undef SCIPboundchgGetNewbound
16519 #undef SCIPboundchgGetVar
16520 #undef SCIPboundchgGetBoundchgtype
16521 #undef SCIPboundchgGetBoundtype
16522 #undef SCIPboundchgIsRedundant
16523 #undef SCIPdomchgGetNBoundchgs
16524 #undef SCIPdomchgGetBoundchg
16525 #undef SCIPholelistGetLeft
16526 #undef SCIPholelistGetRight
16527 #undef SCIPholelistGetNext
16528 #undef SCIPvarGetName
16529 #undef SCIPvarGetNUses
16530 #undef SCIPvarGetData
16531 #undef SCIPvarSetData
16532 #undef SCIPvarSetDelorigData
16533 #undef SCIPvarSetTransData
16534 #undef SCIPvarSetDeltransData
16535 #undef SCIPvarGetStatus
16536 #undef SCIPvarIsOriginal
16537 #undef SCIPvarIsTransformed
16538 #undef SCIPvarIsNegated
16539 #undef SCIPvarGetType
16540 #undef SCIPvarIsBinary
16541 #undef SCIPvarIsIntegral
16542 #undef SCIPvarIsInitial
16543 #undef SCIPvarIsRemovable
16544 #undef SCIPvarIsDeleted
16545 #undef SCIPvarIsDeletable
16546 #undef SCIPvarMarkDeletable
16547 #undef SCIPvarMarkNotDeletable
16548 #undef SCIPvarIsActive
16549 #undef SCIPvarGetIndex
16550 #undef SCIPvarGetProbindex
16551 #undef SCIPvarGetTransVar
16552 #undef SCIPvarGetCol
16553 #undef SCIPvarIsInLP
16554 #undef SCIPvarGetAggrVar
16555 #undef SCIPvarGetAggrScalar
16556 #undef SCIPvarGetAggrConstant
16557 #undef SCIPvarGetMultaggrNVars
16558 #undef SCIPvarGetMultaggrVars
16559 #undef SCIPvarGetMultaggrScalars
16560 #undef SCIPvarGetMultaggrConstant
16561 #undef SCIPvarGetNegatedVar
16562 #undef SCIPvarGetNegationVar
16563 #undef SCIPvarGetNegationConstant
16564 #undef SCIPvarGetObj
16565 #undef SCIPvarGetLbOriginal
16566 #undef SCIPvarGetUbOriginal
16567 #undef SCIPvarGetHolelistOriginal
16568 #undef SCIPvarGetLbGlobal
16569 #undef SCIPvarGetUbGlobal
16570 #undef SCIPvarGetHolelistGlobal
16571 #undef SCIPvarGetBestBoundGlobal
16572 #undef SCIPvarGetWorstBoundGlobal
16573 #undef SCIPvarGetLbLocal
16574 #undef SCIPvarGetUbLocal
16575 #undef SCIPvarGetHolelistLocal
16576 #undef SCIPvarGetBestBoundLocal
16577 #undef SCIPvarGetWorstBoundLocal
16578 #undef SCIPvarGetBestBoundType
16579 #undef SCIPvarGetWorstBoundType
16580 #undef SCIPvarGetLbLazy
16581 #undef SCIPvarGetUbLazy
16582 #undef SCIPvarGetBranchFactor
16583 #undef SCIPvarGetBranchPriority
16584 #undef SCIPvarGetBranchDirection
16585 #undef SCIPvarGetNVlbs
16586 #undef SCIPvarGetVlbVars
16587 #undef SCIPvarGetVlbCoefs
16588 #undef SCIPvarGetVlbConstants
16589 #undef SCIPvarGetNVubs
16590 #undef SCIPvarGetVubVars
16591 #undef SCIPvarGetVubCoefs
16592 #undef SCIPvarGetVubConstants
16593 #undef SCIPvarGetNImpls
16594 #undef SCIPvarGetImplVars
16595 #undef SCIPvarGetImplTypes
16596 #undef SCIPvarGetImplBounds
16597 #undef SCIPvarGetImplIds
16598 #undef SCIPvarGetNCliques
16599 #undef SCIPvarGetCliques
16600 #undef SCIPvarGetLPSol
16601 #undef SCIPvarGetNLPSol
16602 #undef SCIPvarGetBdchgInfoLb
16603 #undef SCIPvarGetNBdchgInfosLb
16604 #undef SCIPvarGetBdchgInfoUb
16605 #undef SCIPvarGetNBdchgInfosUb
16606 #undef SCIPvarGetValuehistory
16607 #undef SCIPvarGetPseudoSol
16608 #undef SCIPvarCatchEvent
16609 #undef SCIPvarDropEvent
16610 #undef SCIPvarGetVSIDS
16611 #undef SCIPvarGetCliqueComponentIdx
16612 #undef SCIPbdchgidxGetPos
16613 #undef SCIPbdchgidxIsEarlierNonNull
16614 #undef SCIPbdchgidxIsEarlier
16615 #undef SCIPbdchginfoGetOldbound
16616 #undef SCIPbdchginfoGetNewbound
16617 #undef SCIPbdchginfoGetVar
16618 #undef SCIPbdchginfoGetChgtype
16619 #undef SCIPbdchginfoGetBoundtype
16620 #undef SCIPbdchginfoGetDepth
16621 #undef SCIPbdchginfoGetPos
16622 #undef SCIPbdchginfoGetIdx
16623 #undef SCIPbdchginfoGetInferVar
16624 #undef SCIPbdchginfoGetInferCons
16625 #undef SCIPbdchginfoGetInferProp
16626 #undef SCIPbdchginfoGetInferInfo
16627 #undef SCIPbdchginfoGetInferBoundtype
16628 #undef SCIPbdchginfoIsRedundant
16629 #undef SCIPbdchginfoHasInferenceReason
16630 #undef SCIPbdchginfoIsTighter
16631 
16632 
16633 /** returns the new value of the bound in the bound change data */
16635  SCIP_BOUNDCHG* boundchg /**< bound change data */
16636  )
16637 {
16638  assert(boundchg != NULL);
16639 
16640  return boundchg->newbound;
16641 }
16642 
16643 /** returns the variable of the bound change in the bound change data */
16645  SCIP_BOUNDCHG* boundchg /**< bound change data */
16646  )
16647 {
16648  assert(boundchg != NULL);
16649 
16650  return boundchg->var;
16651 }
16652 
16653 /** returns the bound change type of the bound change in the bound change data */
16655  SCIP_BOUNDCHG* boundchg /**< bound change data */
16656  )
16657 {
16658  assert(boundchg != NULL);
16659 
16660  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16661 }
16662 
16663 /** returns the bound type of the bound change in the bound change data */
16665  SCIP_BOUNDCHG* boundchg /**< bound change data */
16666  )
16667 {
16668  assert(boundchg != NULL);
16669 
16670  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16671 }
16672 
16673 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16675  SCIP_BOUNDCHG* boundchg /**< bound change data */
16676  )
16677 {
16678  assert(boundchg != NULL);
16679 
16680  return boundchg->redundant;
16681 }
16682 
16683 /** returns the number of bound changes in the domain change data */
16685  SCIP_DOMCHG* domchg /**< domain change data */
16686  )
16687 {
16688  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16689 }
16690 
16691 /** returns a particular bound change in the domain change data */
16693  SCIP_DOMCHG* domchg, /**< domain change data */
16694  int pos /**< position of the bound change in the domain change data */
16695  )
16696 {
16697  assert(domchg != NULL);
16698  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16699 
16700  return &domchg->domchgbound.boundchgs[pos];
16701 }
16702 
16703 /** returns left bound of open interval in hole */
16705  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16706  )
16707 {
16708  assert(holelist != NULL);
16709 
16710  return holelist->hole.left;
16711 }
16712 
16713 /** returns right bound of open interval in hole */
16715  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16716  )
16717 {
16718  assert(holelist != NULL);
16719 
16720  return holelist->hole.right;
16721 }
16722 
16723 /** returns next hole in list */
16725  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16726  )
16727 {
16728  assert(holelist != NULL);
16729 
16730  return holelist->next;
16731 }
16732 
16733 /** returns the name of the variable
16734  *
16735  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16736  */
16737 const char* SCIPvarGetName(
16738  SCIP_VAR* var /**< problem variable */
16739  )
16740 {
16741  assert(var != NULL);
16742 
16743  return var->name;
16744 }
16745 
16746 /** gets number of times, the variable is currently captured */
16747 int SCIPvarGetNUses(
16748  SCIP_VAR* var /**< problem variable */
16749  )
16750 {
16751  assert(var != NULL);
16752 
16753  return var->nuses;
16754 }
16755 
16756 /** returns the user data of the variable */
16758  SCIP_VAR* var /**< problem variable */
16759  )
16760 {
16761  assert(var != NULL);
16762 
16763  return var->vardata;
16764 }
16765 
16766 /** sets the user data for the variable */
16767 void SCIPvarSetData(
16768  SCIP_VAR* var, /**< problem variable */
16769  SCIP_VARDATA* vardata /**< user variable data */
16770  )
16771 {
16772  assert(var != NULL);
16773 
16774  var->vardata = vardata;
16775 }
16776 
16777 /** sets method to free user data for the original variable */
16779  SCIP_VAR* var, /**< problem variable */
16780  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16781  )
16782 {
16783  assert(var != NULL);
16784  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16785 
16786  var->vardelorig = vardelorig;
16787 }
16788 
16789 /** sets method to transform user data of the variable */
16790 void SCIPvarSetTransData(
16791  SCIP_VAR* var, /**< problem variable */
16792  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16793  )
16794 {
16795  assert(var != NULL);
16796  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16797 
16798  var->vartrans = vartrans;
16799 }
16800 
16801 /** sets method to free transformed user data for the variable */
16803  SCIP_VAR* var, /**< problem variable */
16804  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16805  )
16806 {
16807  assert(var != NULL);
16808 
16809  var->vardeltrans = vardeltrans;
16810 }
16811 
16812 /** sets method to copy this variable into sub-SCIPs */
16813 void SCIPvarSetCopyData(
16814  SCIP_VAR* var, /**< problem variable */
16815  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16816  )
16817 {
16818  assert(var != NULL);
16819 
16820  var->varcopy = varcopy;
16821 }
16822 
16823 /** sets the initial flag of a variable; only possible for original or loose variables */
16825  SCIP_VAR* var, /**< problem variable */
16826  SCIP_Bool initial /**< initial flag */
16827  )
16828 {
16829  assert(var != NULL);
16830 
16832  return SCIP_INVALIDCALL;
16833 
16834  var->initial = initial;
16835 
16836  return SCIP_OKAY;
16837 }
16838 
16839 /** sets the removable flag of a variable; only possible for original or loose variables */
16841  SCIP_VAR* var, /**< problem variable */
16842  SCIP_Bool removable /**< removable flag */
16843  )
16844 {
16845  assert(var != NULL);
16846 
16848  return SCIP_INVALIDCALL;
16849 
16850  var->removable = removable;
16851 
16852  return SCIP_OKAY;
16853 }
16854 
16855 /** gets status of variable */
16857  SCIP_VAR* var /**< problem variable */
16858  )
16859 {
16860  assert(var != NULL);
16861 
16862  return (SCIP_VARSTATUS)(var->varstatus);
16863 }
16864 
16865 /** returns whether the variable belongs to the original problem */
16867  SCIP_VAR* var /**< problem variable */
16868  )
16869 {
16870  assert(var != NULL);
16871  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16872 
16876 }
16877 
16878 /** returns whether the variable belongs to the transformed problem */
16880  SCIP_VAR* var /**< problem variable */
16881  )
16882 {
16883  assert(var != NULL);
16884  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16885 
16889 }
16890 
16891 /** returns whether the variable was created by negation of a different variable */
16893  SCIP_VAR* var /**< problem variable */
16894  )
16895 {
16896  assert(var != NULL);
16897 
16898  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16899 }
16900 
16901 /** gets type of variable */
16903  SCIP_VAR* var /**< problem variable */
16904  )
16905 {
16906  assert(var != NULL);
16907 
16908  return (SCIP_VARTYPE)(var->vartype);
16909 }
16910 
16911 /** returns TRUE if the variable is of binary type; this is the case if:
16912  * (1) variable type is binary
16913  * (2) variable type is integer or implicit integer and
16914  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16915  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16916  */
16918  SCIP_VAR* var /**< problem variable */
16919  )
16920 {
16921  assert(var != NULL);
16922 
16923  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16924  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16925 }
16926 
16927 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16929  SCIP_VAR* var /**< problem variable */
16930  )
16931 {
16932  assert(var != NULL);
16933 
16934  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16935 }
16936 
16937 /** returns whether variable's column should be present in the initial root LP */
16939  SCIP_VAR* var /**< problem variable */
16940  )
16941 {
16942  assert(var != NULL);
16943 
16944  return var->initial;
16945 }
16946 
16947 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16949  SCIP_VAR* var /**< problem variable */
16950  )
16951 {
16952  assert(var != NULL);
16953 
16954  return var->removable;
16955 }
16956 
16957 /** returns whether the variable was deleted from the problem */
16959  SCIP_VAR* var /**< problem variable */
16960  )
16961 {
16962  assert(var != NULL);
16963 
16964  return var->deleted;
16965 }
16966 
16967 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16968  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16969  */
16971  SCIP_VAR* var /**< problem variable */
16972  )
16973 {
16974  assert(var != NULL);
16975  assert(var->probindex == -1);
16976 
16977  var->deletable = TRUE;
16978 }
16979 
16980 /** marks the variable to be not deletable from the problem */
16983  )
16984 {
16985  assert(var != NULL);
16986 
16987  var->deletable = FALSE;
16988 }
16989 
16990 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16991  *
16992  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16993  */
16995  SCIP_VAR* var /**< problem variable */
16996  )
16997 {
16998  assert(var != NULL);
16999 
17000  var->delglobalstructs = TRUE;
17001 }
17002 
17003 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17005  SCIP_VAR* var /**< problem variable */
17006  )
17007 {
17008  assert(var != NULL);
17009 
17010  return var->delglobalstructs;
17011 }
17012 
17013 /** returns whether variable is allowed to be deleted completely from the problem */
17016  )
17017 {
17018  assert(var != NULL);
17019 
17020  return var->deletable;
17021 }
17022 
17023 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17025  SCIP_VAR* var /**< problem variable */
17026  )
17027 {
17028  assert(var != NULL);
17029 
17030  return (var->probindex >= 0);
17031 }
17032 
17033 /** gets unique index of variable */
17034 int SCIPvarGetIndex(
17035  SCIP_VAR* var /**< problem variable */
17036  )
17037 {
17038  assert(var != NULL);
17039 
17040  return var->index;
17041 }
17042 
17043 /** gets position of variable in problem, or -1 if variable is not active */
17045  SCIP_VAR* var /**< problem variable */
17046  )
17047 {
17048  assert(var != NULL);
17049 
17050  return var->probindex;
17051 }
17052 
17053 /** gets transformed variable of ORIGINAL variable */
17055  SCIP_VAR* var /**< problem variable */
17056  )
17057 {
17058  assert(var != NULL);
17059  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17060 
17061  return var->data.original.transvar;
17062 }
17063 
17064 /** gets column of COLUMN variable */
17066  SCIP_VAR* var /**< problem variable */
17067  )
17068 {
17069  assert(var != NULL);
17070  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17071 
17072  return var->data.col;
17073 }
17074 
17075 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17077  SCIP_VAR* var /**< problem variable */
17078  )
17079 {
17080  assert(var != NULL);
17081 
17082  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17083 }
17084 
17085 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17087  SCIP_VAR* var /**< problem variable */
17088  )
17089 {
17090  assert(var != NULL);
17092 
17093  return var->data.aggregate.var;
17094 }
17095 
17096 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17098  SCIP_VAR* var /**< problem variable */
17099  )
17100 {
17101  assert(var != NULL);
17103 
17104  return var->data.aggregate.scalar;
17105 }
17106 
17107 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17109  SCIP_VAR* var /**< problem variable */
17110  )
17111 {
17112  assert(var != NULL);
17114 
17115  return var->data.aggregate.constant;
17116 }
17117 
17118 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17120  SCIP_VAR* var /**< problem variable */
17121  )
17122 {
17123  assert(var != NULL);
17124  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17125  assert(!var->donotmultaggr);
17126 
17127  return var->data.multaggr.nvars;
17128 }
17129 
17130 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17132  SCIP_VAR* var /**< problem variable */
17133  )
17134 {
17135  assert(var != NULL);
17136  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17137  assert(!var->donotmultaggr);
17138 
17139  return var->data.multaggr.vars;
17140 }
17141 
17142 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17144  SCIP_VAR* var /**< problem variable */
17145  )
17146 {
17147  assert(var != NULL);
17148  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17149  assert(!var->donotmultaggr);
17150 
17151  return var->data.multaggr.scalars;
17152 }
17153 
17154 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17156  SCIP_VAR* var /**< problem variable */
17157  )
17158 {
17159  assert(var != NULL);
17160  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17161  assert(!var->donotmultaggr);
17162 
17163  return var->data.multaggr.constant;
17164 }
17165 
17166 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17168  SCIP_VAR* var /**< negated problem variable */
17169  )
17170 {
17171  assert(var != NULL);
17172 
17173  return var->negatedvar;
17174 }
17175 
17176 /** gets the negation variable x of a negated variable x' = offset - x */
17178  SCIP_VAR* var /**< negated problem variable */
17179  )
17180 {
17181  assert(var != NULL);
17182  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17183 
17184  return var->negatedvar;
17185 }
17186 
17187 /** gets the negation offset of a negated variable x' = offset - x */
17189  SCIP_VAR* var /**< negated problem variable */
17190  )
17191 {
17192  assert(var != NULL);
17193  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17194 
17195  return var->data.negate.constant;
17196 }
17197 
17198 /** gets objective function value of variable */
17200  SCIP_VAR* var /**< problem variable */
17201  )
17202 {
17203  assert(var != NULL);
17204 
17205  return var->obj;
17206 }
17207 
17208 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17210  SCIP_VAR* var /**< problem variable */
17211  )
17212 {
17213  assert(var != NULL);
17214 
17215  return var->unchangedobj;
17216 }
17217 
17218 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17219  * e.g. obj(x) = 1 this method returns for ~x the value -1
17220  */
17222  SCIP_VAR* var, /**< problem variable */
17223  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17224  )
17225 {
17226  SCIP_VAR* probvar = var;
17227  SCIP_Real mult = 1.0;
17228 
17229  assert(probvar != NULL);
17230  assert(aggrobj != NULL);
17231 
17232  while( probvar != NULL )
17233  {
17234  switch( SCIPvarGetStatus(probvar) )
17235  {
17237  case SCIP_VARSTATUS_LOOSE:
17238  case SCIP_VARSTATUS_COLUMN:
17239  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17240  return SCIP_OKAY;
17241 
17242  case SCIP_VARSTATUS_FIXED:
17243  assert(SCIPvarGetObj(probvar) == 0.0);
17244  (*aggrobj) = 0.0;
17245  return SCIP_OKAY;
17246 
17248  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17249  if ( probvar->data.multaggr.nvars == 1 )
17250  {
17251  assert( probvar->data.multaggr.vars != NULL );
17252  assert( probvar->data.multaggr.scalars != NULL );
17253  assert( probvar->data.multaggr.vars[0] != NULL );
17254  mult *= probvar->data.multaggr.scalars[0];
17255  probvar = probvar->data.multaggr.vars[0];
17256  break;
17257  }
17258  else
17259  {
17260  SCIP_Real tmpobj;
17261  int v;
17262 
17263  (*aggrobj) = 0.0;
17264 
17265  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17266  {
17267  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17268  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17269  }
17270  return SCIP_OKAY;
17271  }
17272 
17273  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17274  assert(probvar->data.aggregate.var != NULL);
17275  mult *= probvar->data.aggregate.scalar;
17276  probvar = probvar->data.aggregate.var;
17277  break;
17278 
17279  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17280  assert(probvar->negatedvar != NULL);
17281  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17282  assert(probvar->negatedvar->negatedvar == probvar);
17283  mult *= -1.0;
17284  probvar = probvar->negatedvar;
17285  break;
17286 
17287  default:
17288  SCIPABORT();
17289  return SCIP_INVALIDDATA; /*lint !e527*/
17290  }
17291  }
17292 
17293  return SCIP_INVALIDDATA;
17294 }
17295 
17296 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17298  SCIP_VAR* var /**< original problem variable */
17299  )
17300 {
17301  assert(var != NULL);
17302  assert(SCIPvarIsOriginal(var));
17303 
17305  return var->data.original.origdom.lb;
17306  else
17307  {
17308  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17309  assert(var->negatedvar != NULL);
17311 
17312  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17313  }
17314 }
17315 
17316 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17318  SCIP_VAR* var /**< original problem variable */
17319  )
17320 {
17321  assert(var != NULL);
17322  assert(SCIPvarIsOriginal(var));
17323 
17325  return var->data.original.origdom.ub;
17326  else
17327  {
17328  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17329  assert(var->negatedvar != NULL);
17331 
17332  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17333  }
17334 }
17335 
17336 /** gets the original hole list of an original variable */
17338  SCIP_VAR* var /**< problem variable */
17339  )
17340 {
17341  assert(var != NULL);
17342  assert(SCIPvarIsOriginal(var));
17343 
17345  return var->data.original.origdom.holelist;
17346 
17347  return NULL;
17348 }
17349 
17350 /** gets global lower bound of variable */
17352  SCIP_VAR* var /**< problem variable */
17353  )
17354 {
17355  assert(var != NULL);
17356 
17357  return var->glbdom.lb;
17358 }
17359 
17360 /** gets global upper bound of variable */
17362  SCIP_VAR* var /**< problem variable */
17363  )
17364 {
17365  assert(var != NULL);
17366 
17367  return var->glbdom.ub;
17368 }
17369 
17370 /** gets the global hole list of an active variable */
17372  SCIP_VAR* var /**< problem variable */
17373  )
17374 {
17375  assert(var != NULL);
17376 
17377  return var->glbdom.holelist;
17378 }
17379 
17380 /** gets best global bound of variable with respect to the objective function */
17382  SCIP_VAR* var /**< problem variable */
17383  )
17384 {
17385  assert(var != NULL);
17386 
17387  if( var->obj >= 0.0 )
17388  return var->glbdom.lb;
17389  else
17390  return var->glbdom.ub;
17391 }
17392 
17393 /** gets worst global bound of variable with respect to the objective function */
17395  SCIP_VAR* var /**< problem variable */
17396  )
17397 {
17398  assert(var != NULL);
17399 
17400  if( var->obj >= 0.0 )
17401  return var->glbdom.ub;
17402  else
17403  return var->glbdom.lb;
17404 }
17405 
17406 /** gets current lower bound of variable */
17408  SCIP_VAR* var /**< problem variable */
17409  )
17410 {
17411  assert(var != NULL);
17412 
17413  return var->locdom.lb;
17414 }
17415 
17416 /** gets current upper bound of variable */
17418  SCIP_VAR* var /**< problem variable */
17419  )
17420 {
17421  assert(var != NULL);
17422 
17423  return var->locdom.ub;
17424 }
17425 
17426 /** gets the current hole list of an active variable */
17428  SCIP_VAR* var /**< problem variable */
17429  )
17430 {
17431  assert(var != NULL);
17432 
17433  return var->locdom.holelist;
17434 }
17435 
17436 /** gets best local bound of variable with respect to the objective function */
17438  SCIP_VAR* var /**< problem variable */
17439  )
17440 {
17441  assert(var != NULL);
17442 
17443  if( var->obj >= 0.0 )
17444  return var->locdom.lb;
17445  else
17446  return var->locdom.ub;
17447 }
17448 
17449 /** gets worst local bound of variable with respect to the objective function */
17451  SCIP_VAR* var /**< problem variable */
17452  )
17453 {
17454  assert(var != NULL);
17455 
17456  if( var->obj >= 0.0 )
17457  return var->locdom.ub;
17458  else
17459  return var->locdom.lb;
17460 }
17461 
17462 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17464  SCIP_VAR* var /**< problem variable */
17465  )
17466 {
17467  assert(var != NULL);
17468 
17469  if( var->obj >= 0.0 )
17470  return SCIP_BOUNDTYPE_LOWER;
17471  else
17472  return SCIP_BOUNDTYPE_UPPER;
17473 }
17474 
17475 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17477  SCIP_VAR* var /**< problem variable */
17478  )
17479 {
17480  assert(var != NULL);
17481 
17482  if( var->obj >= 0.0 )
17483  return SCIP_BOUNDTYPE_UPPER;
17484  else
17485  return SCIP_BOUNDTYPE_LOWER;
17486 }
17487 
17488 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17490  SCIP_VAR* var /**< problem variable */
17491  )
17492 {
17493  assert(var != NULL);
17494 
17495  return var->lazylb;
17496 }
17497 
17498 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17500  SCIP_VAR* var /**< problem variable */
17501  )
17502 {
17503  assert(var != NULL);
17504 
17505  return var->lazyub;
17506 }
17507 
17508 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17509  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17510  */
17512  SCIP_VAR* var /**< problem variable */
17513  )
17514 {
17515  assert(var != NULL);
17516 
17517  return var->branchfactor;
17518 }
17519 
17520 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17521  * with lower priority
17522  */
17524  SCIP_VAR* var /**< problem variable */
17525  )
17526 {
17527  assert(var != NULL);
17528 
17529  return var->branchpriority;
17530 }
17531 
17532 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17534  SCIP_VAR* var /**< problem variable */
17535  )
17536 {
17537  assert(var != NULL);
17538 
17539  return (SCIP_BRANCHDIR)var->branchdirection;
17540 }
17541 
17542 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17543 int SCIPvarGetNVlbs(
17544  SCIP_VAR* var /**< problem variable */
17545  )
17546 {
17547  assert(var != NULL);
17548 
17549  return SCIPvboundsGetNVbds(var->vlbs);
17550 }
17551 
17552 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17553  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17554  */
17556  SCIP_VAR* var /**< problem variable */
17557  )
17558 {
17559  assert(var != NULL);
17560 
17561  return SCIPvboundsGetVars(var->vlbs);
17562 }
17563 
17564 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17566  SCIP_VAR* var /**< problem variable */
17567  )
17568 {
17569  assert(var != NULL);
17570 
17571  return SCIPvboundsGetCoefs(var->vlbs);
17572 }
17573 
17574 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17576  SCIP_VAR* var /**< problem variable */
17577  )
17578 {
17579  assert(var != NULL);
17580 
17581  return SCIPvboundsGetConstants(var->vlbs);
17582 }
17583 
17584 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17585 int SCIPvarGetNVubs(
17586  SCIP_VAR* var /**< problem variable */
17587  )
17588 {
17589  assert(var != NULL);
17590 
17591  return SCIPvboundsGetNVbds(var->vubs);
17592 }
17593 
17594 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17595  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17596  */
17598  SCIP_VAR* var /**< problem variable */
17599  )
17600 {
17601  assert(var != NULL);
17602 
17603  return SCIPvboundsGetVars(var->vubs);
17604 }
17605 
17606 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17608  SCIP_VAR* var /**< problem variable */
17609  )
17610 {
17611  assert(var != NULL);
17612 
17613  return SCIPvboundsGetCoefs(var->vubs);
17614 }
17615 
17616 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17618  SCIP_VAR* var /**< problem variable */
17619  )
17620 {
17621  assert(var != NULL);
17622 
17623  return SCIPvboundsGetConstants(var->vubs);
17624 }
17625 
17626 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17627  * there are no implications for nonbinary variable x
17628  */
17629 int SCIPvarGetNImpls(
17630  SCIP_VAR* var, /**< active problem variable */
17631  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17632  )
17633 {
17634  assert(var != NULL);
17635  assert(SCIPvarIsActive(var));
17636 
17637  return SCIPimplicsGetNImpls(var->implics, varfixing);
17638 }
17639 
17640 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17641  * problem variable x, there are no implications for nonbinary variable x;
17642  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17643  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17644  * (see SCIPvarGetIndex())
17645  */
17647  SCIP_VAR* var, /**< active problem variable */
17648  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17649  )
17650 {
17651  assert(var != NULL);
17652  assert(SCIPvarIsActive(var));
17653 
17654  return SCIPimplicsGetVars(var->implics, varfixing);
17655 }
17656 
17657 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17658  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17659  * there are no implications for nonbinary variable x
17660  */
17662  SCIP_VAR* var, /**< active problem variable */
17663  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17664  )
17665 {
17666  assert(var != NULL);
17667  assert(SCIPvarIsActive(var));
17668 
17669  return SCIPimplicsGetTypes(var->implics, varfixing);
17670 }
17671 
17672 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17673  * variable x, there are no implications for nonbinary variable x
17674  */
17676  SCIP_VAR* var, /**< active problem variable */
17677  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17678  )
17679 {
17680  assert(var != NULL);
17681  assert(SCIPvarIsActive(var));
17682 
17683  return SCIPimplicsGetBounds(var->implics, varfixing);
17684 }
17685 
17686 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17687  * there are no implications for nonbinary variable x.
17688  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17689  * its id is negative, otherwise it is nonnegative.
17690  */
17691 int* SCIPvarGetImplIds(
17692  SCIP_VAR* var, /**< active problem variable */
17693  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17694  )
17695 {
17696  assert(var != NULL);
17697  assert(SCIPvarIsActive(var));
17698 
17699  return SCIPimplicsGetIds(var->implics, varfixing);
17700 }
17701 
17702 /** gets number of cliques, the active variable is contained in */
17703 int SCIPvarGetNCliques(
17704  SCIP_VAR* var, /**< active problem variable */
17705  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17706  )
17707 {
17708  assert(var != NULL);
17709 
17710  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17711 }
17712 
17713 /** gets array of cliques, the active variable is contained in */
17715  SCIP_VAR* var, /**< active problem variable */
17716  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17717  )
17718 {
17719  assert(var != NULL);
17720 
17721  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17722 }
17723 
17724 /** gets primal LP solution value of variable */
17726  SCIP_VAR* var /**< problem variable */
17727  )
17728 {
17729  assert(var != NULL);
17730 
17732  return SCIPcolGetPrimsol(var->data.col);
17733  else
17734  return SCIPvarGetLPSol_rec(var);
17735 }
17736 
17737 /** gets primal NLP solution value of variable */
17739  SCIP_VAR* var /**< problem variable */
17740  )
17741 {
17742  assert(var != NULL);
17743 
17745  return var->nlpsol;
17746  else
17747  return SCIPvarGetNLPSol_rec(var);
17748 }
17749 
17750 /** return lower bound change info at requested position */
17752  SCIP_VAR* var, /**< problem variable */
17753  int pos /**< requested position */
17754  )
17755 {
17756  assert(pos >= 0);
17757  assert(pos < var->nlbchginfos);
17758 
17759  return &var->lbchginfos[pos];
17760 }
17761 
17762 /** gets the number of lower bound change info array */
17764  SCIP_VAR* var /**< problem variable */
17765  )
17766 {
17767  return var->nlbchginfos;
17768 }
17769 
17770 /** return upper bound change info at requested position */
17772  SCIP_VAR* var, /**< problem variable */
17773  int pos /**< requested position */
17774  )
17775 {
17776  assert(pos >= 0);
17777  assert(pos < var->nubchginfos);
17778 
17779  return &var->ubchginfos[pos];
17780 }
17781 
17782 /** gets the number upper bound change info array */
17784  SCIP_VAR* var /**< problem variable */
17785  )
17786 {
17787  assert(var != NULL);
17788 
17789  return var->nubchginfos;
17790 }
17791 
17792 /** returns the value based history for the variable */
17794  SCIP_VAR* var /**< problem variable */
17795  )
17796 {
17797  assert(var != NULL);
17798 
17799  return var->valuehistory;
17800 }
17801 
17802 /** gets pseudo solution value of variable */
17804  SCIP_VAR* var /**< problem variable */
17805  )
17806 {
17807  assert(var != NULL);
17808 
17810  return SCIPvarGetBestBoundLocal(var);
17811  else
17812  return SCIPvarGetPseudoSol_rec(var);
17813 }
17814 
17815 /** returns the variable's VSIDS score */
17817  SCIP_VAR* var, /**< problem variable */
17818  SCIP_STAT* stat, /**< problem statistics */
17819  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17820  )
17821 {
17822  assert(var != NULL);
17823 
17825  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17826  else
17827  return SCIPvarGetVSIDS_rec(var, stat, dir);
17828 }
17829 
17830 /** includes event handler with given data in variable's event filter */
17832  SCIP_VAR* var, /**< problem variable */
17833  BMS_BLKMEM* blkmem, /**< block memory */
17834  SCIP_SET* set, /**< global SCIP settings */
17835  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17836  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17837  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17838  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17839  )
17840 {
17841  assert(var != NULL);
17842  assert(set != NULL);
17843  assert(var->scip == set->scip);
17844  assert(var->eventfilter != NULL);
17845  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17846  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17847  assert(SCIPvarIsTransformed(var));
17848 
17849  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
17850  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17851 
17852  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17853 
17854  return SCIP_OKAY;
17855 }
17856 
17857 /** deletes event handler with given data from variable's event filter */
17859  SCIP_VAR* var, /**< problem variable */
17860  BMS_BLKMEM* blkmem, /**< block memory */
17861  SCIP_SET* set, /**< global SCIP settings */
17862  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17863  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17864  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17865  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17866  )
17867 {
17868  assert(var != NULL);
17869  assert(set != NULL);
17870  assert(var->scip == set->scip);
17871  assert(var->eventfilter != NULL);
17872  assert(SCIPvarIsTransformed(var));
17873 
17874  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17875  (void*)eventdata);
17876 
17877  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17878 
17879  return SCIP_OKAY;
17880 }
17881 
17882 /** returns the position of the bound change index */
17883 int SCIPbdchgidxGetPos(
17884  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17885  )
17886 {
17887  assert(bdchgidx != NULL);
17888 
17889  return bdchgidx->pos;
17890 }
17891 
17892 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17894  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17895  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17896  )
17897 {
17898  assert(bdchgidx1 != NULL);
17899  assert(bdchgidx1->depth >= -2);
17900  assert(bdchgidx1->pos >= 0);
17901  assert(bdchgidx2 != NULL);
17902  assert(bdchgidx2->depth >= -2);
17903  assert(bdchgidx2->pos >= 0);
17904 
17905  return (bdchgidx1->depth < bdchgidx2->depth)
17906  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17907 }
17908 
17909 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17910  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17911  * last bound change was applied to the current node
17912  */
17914  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17915  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17916  )
17917 {
17918  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17919  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17920  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17921  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17922 
17923  if( bdchgidx1 == NULL )
17924  return FALSE;
17925  else if( bdchgidx2 == NULL )
17926  return TRUE;
17927  else
17928  return (bdchgidx1->depth < bdchgidx2->depth)
17929  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17930 }
17931 
17932 /** returns old bound that was overwritten for given bound change information */
17934  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17935  )
17936 {
17937  assert(bdchginfo != NULL);
17938 
17939  return bdchginfo->oldbound;
17940 }
17941 
17942 /** returns new bound installed for given bound change information */
17944  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17945  )
17946 {
17947  assert(bdchginfo != NULL);
17948 
17949  return bdchginfo->newbound;
17950 }
17951 
17952 /** returns variable that belongs to the given bound change information */
17954  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17955  )
17956 {
17957  assert(bdchginfo != NULL);
17958 
17959  return bdchginfo->var;
17960 }
17961 
17962 /** returns whether the bound change information belongs to a branching decision or a deduction */
17964  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17965  )
17966 {
17967  assert(bdchginfo != NULL);
17968 
17969  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17970 }
17971 
17972 /** returns whether the bound change information belongs to a lower or upper bound change */
17974  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17975  )
17976 {
17977  assert(bdchginfo != NULL);
17978 
17979  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17980 }
17981 
17982 /** returns depth level of given bound change information */
17984  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17985  )
17986 {
17987  assert(bdchginfo != NULL);
17988 
17989  return bdchginfo->bdchgidx.depth;
17990 }
17991 
17992 /** returns bound change position in its depth level of given bound change information */
17994  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17995  )
17996 {
17997  assert(bdchginfo != NULL);
17998 
17999  return bdchginfo->bdchgidx.pos;
18000 }
18001 
18002 /** returns bound change index of given bound change information */
18004  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18005  )
18006 {
18007  assert(bdchginfo != NULL);
18008 
18009  return &bdchginfo->bdchgidx;
18010 }
18011 
18012 /** returns inference variable of given bound change information */
18014  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18015  )
18016 {
18017  assert(bdchginfo != NULL);
18020 
18021  return bdchginfo->inferencedata.var;
18022 }
18023 
18024 /** returns inference constraint of given bound change information */
18026  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18027  )
18028 {
18029  assert(bdchginfo != NULL);
18031  assert(bdchginfo->inferencedata.reason.cons != NULL);
18032 
18033  return bdchginfo->inferencedata.reason.cons;
18034 }
18035 
18036 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18038  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18039  )
18040 {
18041  assert(bdchginfo != NULL);
18043 
18044  return bdchginfo->inferencedata.reason.prop;
18045 }
18046 
18047 /** returns inference user information of given bound change information */
18049  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18050  )
18051 {
18052  assert(bdchginfo != NULL);
18055 
18056  return bdchginfo->inferencedata.info;
18057 }
18058 
18059 /** returns inference bound of inference variable of given bound change information */
18061  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18062  )
18063 {
18064  assert(bdchginfo != NULL);
18067 
18068  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18069 }
18070 
18071 /** returns the relaxed bound change type */
18073  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18074  )
18075 {
18076  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18077 }
18078 
18079 
18080 /** returns whether the bound change information belongs to a redundant bound change */
18082  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18083  )
18084 {
18085  assert(bdchginfo != NULL);
18086  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18087 
18088  return bdchginfo->redundant;
18089 }
18090 
18091 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18093  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18094  )
18095 {
18096  assert(bdchginfo != NULL);
18097 
18100  && bdchginfo->inferencedata.reason.prop != NULL);
18101 }
18102 
18103 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18104  * has a tighter new bound as the second bound change
18105  */
18107  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18108  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18109  )
18110 {
18111  assert(bdchginfo1 != NULL);
18112  assert(bdchginfo2 != NULL);
18113  assert(bdchginfo1->var == bdchginfo2->var);
18114  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18115 
18116  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18117  ? bdchginfo1->newbound > bdchginfo2->newbound
18118  : bdchginfo1->newbound < bdchginfo2->newbound);
18119 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:554
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11485
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 SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:94
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18073
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17438
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_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2973
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14892
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5953
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16880
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3316
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:457
#define NULL
Definition: def.h:253
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13612
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
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9098
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:15019
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 SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16893
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_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17428
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:14539
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8980
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13306
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:10089
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:16748
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12772
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13496
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17474
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17098
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:6059
union SCIP_BoundChg::@12 data
internal methods for branch and bound tree
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:15800
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:227
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5855
unsigned int inferboundtype
Definition: struct_var.h:93
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17077
char * name
Definition: struct_var.h:229
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:965
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3241
unsigned int boundchgtype
Definition: struct_var.h:114
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16291
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 SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6140
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17055
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:6553
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6351
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1686
#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:6903
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5675
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_EXPORT SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14106
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17739
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:4578
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16803
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_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:14272
#define SCIP_MAXSTRLEN
Definition: def.h:274
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17794
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15187
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:6285
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17512
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17500
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
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:250
#define MAXABSVBCOEF
Definition: var.c:70
#define SQR(x)
Definition: def.h:205
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1695
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12906
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18082
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15854
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_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7187
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17726
SCIP_Real constant
Definition: struct_var.h:184
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:8282
SCIP_HISTORY * historycrun
Definition: struct_var.h:245
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:171
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17772
SCIP_EXPORT SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7347
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8690
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16971
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3409
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1425
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6344
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_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:8590
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:2421
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:6480
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
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2310
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:243
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:5898
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14625
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12426
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17804
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:128
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:17832
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16918
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_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17647
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:5818
#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:4388
#define FALSE
Definition: def.h:73
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10394
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:189
#define EPSISINT(x, eps)
Definition: def.h:201
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17464
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6494
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 SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17200
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16635
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:3348
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16685
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:68
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:258
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17372
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3043
SCIP_Real constant
Definition: struct_var.h:194
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11963
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
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16903
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14511
#define TRUE
Definition: def.h:72
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5799
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14848
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 SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15320
#define MAXIMPLSCLOSURE
Definition: var.c:67
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:688
int nlbchginfos
Definition: struct_var.h:261
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16311
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2868
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1684
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
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12355
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:10444
#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:7965
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5833
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5503
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16779
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:7939
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2827
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:7046
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17025
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12563
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:15555
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16982
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17676
SCIP_EXPORT void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
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:10767
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11428
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:11500
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16647
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16857
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17884
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11493
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_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13206
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16366
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13867
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1691
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6235
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:249
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11313
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:667
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3327
SCIP_HOLECHG * holechgs
Definition: struct_var.h:134
SCIP_Real obj
Definition: struct_var.h:203
SCIP_EXPORT SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7627
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:13485
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:232
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:5825
internal methods for LP management
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16657
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17556
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12635
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_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_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:61
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:2274
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17144
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_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:12496
int nrootboundchgs
Definition: struct_stat.h:205
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16791
#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:7264
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:166
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12842
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15416
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:500
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18014
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1414
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16939
SCIP_Real conflictrelaxedub
Definition: struct_var.h:216
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:7688
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17964
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3240
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5993
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12380
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:5933
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4373
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10993
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:12959
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16825
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16675
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:704
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16693
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:246
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:215
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11183
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13965
SCIP_AGGREGATE aggregate
Definition: struct_var.h:225
SCIP_Real lazylb
Definition: struct_var.h:217
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12749
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:451
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16738
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:7302
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17015
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
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7210
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:7522
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4357
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16929
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18107
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:12955
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17692
#define SCIPerrorMessage
Definition: pub_message.h:45
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14129
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11772
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10364
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:16308
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:14415
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_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17168
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15710
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17490
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17630
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:5984
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16655
int lbchginfossize
Definition: struct_var.h:260
unsigned int varstatus
Definition: struct_var.h:274
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17477
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17524
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17984
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2782
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:6172
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17222
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14014
SCIP_Real primsolavg
Definition: struct_var.h:212
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:3064
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17608
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:931
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3434
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:251
SCIP_HOLECHG * holechgs
Definition: struct_var.h:144
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:6729
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
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
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:4880
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:1688
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
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:13687
SCIP_NEGATE negate
Definition: struct_var.h:227
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4299
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16031
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:7355
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13352
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:165
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:16814
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3269
#define REALABS(x)
Definition: def.h:188
int nparentvars
Definition: struct_var.h:255
SCIP_Real unchangedobj
Definition: struct_var.h:204
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11398
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:3635
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15954
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:9717
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14756
internal methods for global SCIP settings
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14234
#define SCIP_CALL(x)
Definition: def.h:365
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17586
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16690
SCIP_VBOUNDS * vubs
Definition: struct_var.h:238
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6439
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:184
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:14935
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16667
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2346
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15467
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14061
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:9436
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5626
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3277
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18038
Definition: grphload.c:88
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:14149
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:11127
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:7814
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:245
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17109
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14803
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15898
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2903
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17189
SCIP_EXPORT void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
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
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10663
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:246
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:323
int var_probindex
Definition: struct_lp.h:169
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16314
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:6269
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3338
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17066
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:454
internal methods for problem variables
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:5957
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11057
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:5106
#define SCIP_UNKNOWN
Definition: def.h:185
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_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10643
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:458
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17178
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:15103
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:6404
SCIP_VAR * var
Definition: struct_var.h:90
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:88
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:8709
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:637
#define SCIP_Bool
Definition: def.h:70
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17156
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2770
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18093
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17894
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:445
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1066
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11712
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16705
unsigned int deletable
Definition: struct_var.h:270
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15512
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5851
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16841
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6196
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17362
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12761
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17464
SCIP_Bool divingobjchg
Definition: struct_lp.h:366
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:8055
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:456
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:616
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8963
unsigned int deleted
Definition: struct_var.h:271
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3324
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3694
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17451
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3285
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11479
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18049
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16867
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_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15275
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17210
#define MIN(x, y)
Definition: def.h:223
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3355
public methods for LP management
unsigned int removable
Definition: struct_var.h:269
#define SCIPsetDebugMsg
Definition: set.h:1720
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3303
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16768
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2568
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8348
unsigned int redundant
Definition: struct_var.h:95
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15232
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10890
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16351
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17914
int closestvlbidx
Definition: struct_var.h:266
#define EPSLE(x, y, eps)
Definition: def.h:191
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17974
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18061
int nuses
Definition: struct_var.h:256
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15612
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:10676
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10929
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:124
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:158
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:8461
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16959
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17298
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:13413
datastructures for problem statistics
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17715
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:615
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:14675
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:9228
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17408
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3739
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16725
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:12683
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2245
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17994
int conflictubcount
Definition: struct_var.h:265
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3253
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
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:9509
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3184
#define SCIP_REAL_MAX
Definition: def.h:165
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:2840
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
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17395
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:13759
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3499
SCIP_Real newbound
Definition: struct_var.h:84
#define SCIP_REAL_MIN
Definition: def.h:166
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3540
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17418
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
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2596
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:7236
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17954
#define MAX(x, y)
Definition: def.h:222
#define SCIP_DEFAULT_INFINITY
Definition: def.h:169
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1201
SCIP_HOLELIST * next
Definition: struct_var.h:52
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6184
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18026
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:628
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:442
unsigned int boundtype
Definition: struct_var.h:115
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1698
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:5272
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8357
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3465
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
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_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15667
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17352
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:3804
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16799
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12056
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17566
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17120
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:14349
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17576
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_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17752
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10263
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
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:9000
SCIP_Real * scalars
Definition: struct_var.h:185
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17784
SCIP_IMPLICS * implics
Definition: struct_var.h:239
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6029
datastructures for problem variables
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16995
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_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8947
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8076
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:9129
#define SCIP_Real
Definition: def.h:164
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:2669
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_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16150
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_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2355
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12268
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14108
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17817
#define SCIP_INVALID
Definition: def.h:184
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
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:2485
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16010
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2230
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:445
SCIP_Real branchfactor
Definition: struct_var.h:205
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17662
unsigned int donotmultaggr
Definition: struct_var.h:272
#define SCIP_Longint
Definition: def.h:149
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6672
SCIP_Real nlpsol
Definition: struct_var.h:211
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10972
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:2544
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15753
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:8838
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8216
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2809
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16725
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_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16645
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2847
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17045
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:6442
SCIP_Bool collectvarhistory
Definition: struct_stat.h:263
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11804
SCIP_VAR * negatedvar
Definition: struct_var.h:236
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17005
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3389
SCIP_Real newbound
Definition: struct_var.h:109
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:8409
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15884
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6252
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6512
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:441
unsigned int delglobalstructs
Definition: struct_var.h:278
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6694
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16758
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:17859
SCIP_Real rootsol
Definition: struct_var.h:206
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2476
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13984
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13337
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17087
SCIP_HISTORY * history
Definition: struct_var.h:244
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17318
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15365
int nrootintfixingsrun
Definition: struct_stat.h:208
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:427
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17704
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12141
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16665
#define SCIP_CALL_ABORT(x)
Definition: def.h:344
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17338
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16949
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_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8942
#define SCIP_ALLOC(x)
Definition: def.h:376
#define SCIPABORT()
Definition: def.h:337
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13272
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_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17534
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8150
unsigned int applied
Definition: struct_var.h:94
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16715
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17618
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:10852
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17598
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11692
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16271
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:447
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5887
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13552
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17934
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16439
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:5710
SCIP_Real left
Definition: struct_var.h:44
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
#define EPSZ(x, eps)
Definition: def.h:194
#define ABS(x)
Definition: def.h:218
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17132
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18004
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17944
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:11246
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_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17382
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6483
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17544
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14180
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17035
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:14484
public methods for propagators
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1500
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
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11436
SCIP_Real scalar
Definition: struct_var.h:176
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17764
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10912