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-2014 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @brief methods for problem variables
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Marc Pfetsch
23  * @author Michael Winkler
24  * @author Kati Wolter
25  * @author Stefan Vigerske
26  *
27  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
28  * corresponding linear constraint if it exists. This seems to require some work, since the linear
29  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
30  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
31  * changed. This has to be done with care in order to not loose the performance gains of
32  * multi-aggregation.
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "scip/def.h"
42 #include "scip/prop.h"
43 #include "scip/relax.h"
44 #include "scip/var.h"
45 #include "scip/cons.h"
46 #include "scip/event.h"
47 #include "scip/history.h"
48 #include "scip/implics.h"
49 #include "scip/lp.h"
50 #include "scip/primal.h"
51 #include "scip/prob.h"
52 #include "scip/set.h"
53 #include "scip/sol.h"
54 #include "scip/stat.h"
55 #include "scip/tree.h"
56 
57 #include "scip/debug.h"
58 
59 #include "scip/pub_message.h"
60 #include "scip/pub_history.h"
61 
62 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
63  * in implication graph */
64 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
65 
66 /*
67  * hole, holelist, and domain methods
68  */
69 
70 /** creates a new holelist element */
71 static
73  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
74  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
75  SCIP_SET* set, /**< global SCIP settings */
76  SCIP_Real left, /**< left bound of open interval in new hole */
77  SCIP_Real right /**< right bound of open interval in new hole */
78  )
79 {
80  assert(holelist != NULL);
81  assert(blkmem != NULL);
82  assert(SCIPsetIsLT(set, left, right));
83 
84  SCIPdebugMessage("create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
85 
86  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
87  (*holelist)->hole.left = left;
88  (*holelist)->hole.right = right;
89  (*holelist)->next = NULL;
90 
91  return SCIP_OKAY;
92 }
93 
94 /** frees all elements in the holelist */
95 static
96 void holelistFree(
97  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
98  BMS_BLKMEM* blkmem /**< block memory for target holelist */
99  )
100 {
101  assert(holelist != NULL);
102  assert(blkmem != NULL);
103 
104  while( *holelist != NULL )
105  {
106  SCIP_HOLELIST* next;
107 
108  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
109  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
110 
111  next = (*holelist)->next;
112  BMSfreeBlockMemory(blkmem, holelist);
113  assert(*holelist == NULL);
114 
115  *holelist = next;
116  }
117  assert(*holelist == NULL);
118 }
119 
120 /** duplicates a list of holes */
121 static
123  SCIP_HOLELIST** target, /**< pointer to target holelist */
124  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
125  SCIP_SET* set, /**< global SCIP settings */
126  SCIP_HOLELIST* source /**< holelist to duplicate */
127  )
128 {
129  assert(target != NULL);
130 
131  while( source != NULL )
132  {
133  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
134  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
135  source = source->next;
136  target = &(*target)->next;
137  }
138 
139  return SCIP_OKAY;
140 }
141 
142 /** adds a hole to the domain */
143 static
145  SCIP_DOM* dom, /**< domain to add hole to */
146  BMS_BLKMEM* blkmem, /**< block memory */
147  SCIP_SET* set, /**< global SCIP settings */
148  SCIP_Real left, /**< left bound of open interval in new hole */
149  SCIP_Real right, /**< right bound of open interval in new hole */
150  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
151  )
152 {
153  SCIP_HOLELIST** insertpos;
154  SCIP_HOLELIST* next;
155 
156  assert(dom != NULL);
157  assert(added != NULL);
158 
159  /* search for the position of the new hole */
160  insertpos = &dom->holelist;
161  while( *insertpos != NULL && (*insertpos)->hole.left < left )
162  insertpos = &(*insertpos)->next;
163 
164  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
165  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
166  {
167  SCIPdebugMessage("new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
168  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
169  *added = FALSE;
170  return SCIP_OKAY;
171  }
172 
173  /* add hole */
174  *added = TRUE;
175 
176  next = *insertpos;
177  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
178  (*insertpos)->next = next;
179 
180  return SCIP_OKAY;
181 }
182 
183 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
184 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
185  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
186  * merge */
187 static
188 void domMerge(
189  SCIP_DOM* dom, /**< domain to merge */
190  BMS_BLKMEM* blkmem, /**< block memory */
191  SCIP_SET* set, /**< global SCIP settings */
192  SCIP_Real* newlb, /**< pointer to store new lower bound */
193  SCIP_Real* newub /**< pointer to store new upper bound */
194  )
195 {
196  SCIP_HOLELIST** holelistptr;
197  SCIP_HOLELIST** lastnextptr;
198  SCIP_Real* lastrightptr;
199 
200  assert(dom != NULL);
201  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
202 
203 #ifndef NDEBUG
204  {
205  /* check if the holelist is sorted w.r.t. to the left interval bounds */
206  SCIP_Real lastleft;
207 
208  holelistptr = &dom->holelist;
209 
210  lastleft = -SCIPsetInfinity(set);
211 
212  while( *holelistptr != NULL )
213  {
214  if( (*holelistptr)->next != NULL )
215  {
216  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
217  lastleft = (*holelistptr)->hole.left;
218  }
219 
220  holelistptr = &(*holelistptr)->next;
221  }
222  }
223 #endif
224 
225  SCIPdebugMessage("merge hole list\n");
226 
227  holelistptr = &dom->holelist;
228  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
229  lastnextptr = holelistptr;
230 
231  while( *holelistptr != NULL )
232  {
233  SCIPdebugMessage("check hole (%.15g,%.15g) last right interval was <%.15g>\n",
234  (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
235 
236  /* check that the hole is not empty */
237  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
238 
239  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
240  {
241  /* the remaining holes start behind the upper bound: remove them */
242  SCIPdebugMessage("remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
243  holelistFree(holelistptr, blkmem);
244  assert(*holelistptr == NULL);
245 
246  /* unlink this hole from the previous hole */
247  *lastnextptr = NULL;
248  }
249  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
250  {
251  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
252  SCIPdebugMessage("upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
253 
254  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
255 
256  /* adjust upper bound */
257  dom->ub = (*holelistptr)->hole.left;
258 
259  if(newub != NULL )
260  *newub = (*holelistptr)->hole.left;
261 
262  /* remove remaining hole list */
263  holelistFree(holelistptr, blkmem);
264  assert(*holelistptr == NULL);
265 
266  /* unlink this hole from the previous hole */
267  *lastnextptr = NULL;
268  }
269  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
270  {
271  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
272  * the last hole, delete this hole */
273  SCIP_HOLELIST* nextholelist;
274 
275  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
276  {
277  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
278  * the lower bound */
279  SCIPdebugMessage("lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
280  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
281 
282  /* adjust lower bound */
283  dom->lb = *lastrightptr;
284 
285  if(newlb != NULL )
286  *newlb = *lastrightptr;
287  }
288  else
289  {
290  SCIPdebugMessage("current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
291  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
292  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
293  }
294  nextholelist = (*holelistptr)->next;
295  (*holelistptr)->next = NULL;
296  holelistFree(holelistptr, blkmem);
297 
298  /* connect the linked list after removing the hole */
299  *lastnextptr = nextholelist;
300 
301  /* get next hole */
302  *holelistptr = nextholelist;
303  }
304  else
305  {
306  /* the holes do not overlap: update lastholelist and lastrightptr */
307  lastrightptr = &(*holelistptr)->hole.right;
308  lastnextptr = &(*holelistptr)->next;
309 
310  /* get next hole */
311  holelistptr = &(*holelistptr)->next;
312  }
313  }
314 
315 #ifndef NDEBUG
316  {
317  /* check that holes are merged */
318  SCIP_Real lastright;
319 
320  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
321  holelistptr = &dom->holelist;
322 
323  while( *holelistptr != NULL )
324  {
325  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
326  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
327 
328  /* check the hole property (check that the hole is not empty) */
329  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
330  lastright = (*holelistptr)->hole.right;
331 
332  /* get next hole */
333  holelistptr = &(*holelistptr)->next;
334  }
335 
336  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
337  assert( SCIPsetIsLE(set, lastright, dom->ub) );
338  }
339 #endif
340 }
341 
342 /*
343  * domain change methods
344  */
345 
346 /** ensures, that bound change info array for lower bound changes can store at least num entries */
347 static
349  SCIP_VAR* var, /**< problem variable */
350  BMS_BLKMEM* blkmem, /**< block memory */
351  SCIP_SET* set, /**< global SCIP settings */
352  int num /**< minimum number of entries to store */
353  )
354 {
355  assert(var != NULL);
356  assert(var->nlbchginfos <= var->lbchginfossize);
357  assert(SCIPvarIsTransformed(var));
358 
359  if( num > var->lbchginfossize )
360  {
361  int newsize;
362 
363  newsize = SCIPsetCalcMemGrowSize(set, num);
364  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
365  var->lbchginfossize = newsize;
366  }
367  assert(num <= var->lbchginfossize);
368 
369  return SCIP_OKAY;
370 }
371 
372 /** ensures, that bound change info array for upper bound changes can store at least num entries */
373 static
375  SCIP_VAR* var, /**< problem variable */
376  BMS_BLKMEM* blkmem, /**< block memory */
377  SCIP_SET* set, /**< global SCIP settings */
378  int num /**< minimum number of entries to store */
379  )
380 {
381  assert(var != NULL);
382  assert(var->nubchginfos <= var->ubchginfossize);
383  assert(SCIPvarIsTransformed(var));
384 
385  if( num > var->ubchginfossize )
386  {
387  int newsize;
388 
389  newsize = SCIPsetCalcMemGrowSize(set, num);
390  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
391  var->ubchginfossize = newsize;
392  }
393  assert(num <= var->ubchginfossize);
394 
395  return SCIP_OKAY;
396 }
397 
398 /** adds domain change info to the variable's lower bound change info array */
399 static
401  SCIP_VAR* var, /**< problem variable */
402  BMS_BLKMEM* blkmem, /**< block memory */
403  SCIP_SET* set, /**< global SCIP settings */
404  SCIP_Real oldbound, /**< old value for bound */
405  SCIP_Real newbound, /**< new value for bound */
406  int depth, /**< depth in the tree, where the bound change takes place */
407  int pos, /**< position of the bound change in its bound change array */
408  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
409  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
410  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
411  int inferinfo, /**< user information for inference to help resolving the conflict */
412  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
413  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
414  )
415 {
416  assert(var != NULL);
417  assert(SCIPsetIsLT(set, oldbound, newbound));
418  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
419  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
420  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
421  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
422  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
423  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
424  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
425 
426  SCIPdebugMessage("adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
427  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos,
428  infercons != NULL ? "cons" : "prop",
429  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
430  oldbound, newbound);
431 
432  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
433  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
434  var->lbchginfos[var->nlbchginfos].newbound = newbound;
435  var->lbchginfos[var->nlbchginfos].var = var;
436  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
437  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
438  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
439  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
440  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
441  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
442  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
443  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
444  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
445 
446  /**@note The "pos" data member of the bound change info has a size of 27 bits */
447  assert(var->nlbchginfos < 1 << 27);
448 
449  switch( boundchgtype )
450  {
452  break;
454  assert(infercons != NULL);
455  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
456  break;
458  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
459  break;
460  default:
461  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
462  return SCIP_INVALIDDATA;
463  }
464 
465  var->nlbchginfos++;
466 
467  assert(var->nlbchginfos < 2
469  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
470 
471  return SCIP_OKAY;
472 }
473 
474 /** adds domain change info to the variable's upper bound change info array */
475 static
477  SCIP_VAR* var, /**< problem variable */
478  BMS_BLKMEM* blkmem, /**< block memory */
479  SCIP_SET* set, /**< global SCIP settings */
480  SCIP_Real oldbound, /**< old value for bound */
481  SCIP_Real newbound, /**< new value for bound */
482  int depth, /**< depth in the tree, where the bound change takes place */
483  int pos, /**< position of the bound change in its bound change array */
484  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
485  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
486  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
487  int inferinfo, /**< user information for inference to help resolving the conflict */
488  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
489  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
490  )
491 {
492  assert(var != NULL);
493  assert(SCIPsetIsGT(set, oldbound, newbound));
494  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
495  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
496  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
497  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
498  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
499  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
500  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
501 
502  SCIPdebugMessage("adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
503  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos,
504  infercons != NULL ? "cons" : "prop",
505  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
506  oldbound, newbound);
507 
508  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
509  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
510  var->ubchginfos[var->nubchginfos].newbound = newbound;
511  var->ubchginfos[var->nubchginfos].var = var;
512  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
513  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
514  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
515  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
516  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
517  var->ubchginfos[var->nubchginfos].redundant = FALSE;
518  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
519  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
520  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
521 
522  /**@note The "pos" data member of the bound change info has a size of 27 bits */
523  assert(var->nubchginfos < 1 << 27);
524 
525  switch( boundchgtype )
526  {
528  break;
530  assert(infercons != NULL);
531  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
532  break;
534  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
535  break;
536  default:
537  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
538  return SCIP_INVALIDDATA;
539  }
540 
541  var->nubchginfos++;
542 
543  assert(var->nubchginfos < 2
545  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
546 
547  return SCIP_OKAY;
548 }
549 
550 /** applies single bound change */
552  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
553  BMS_BLKMEM* blkmem, /**< block memory */
554  SCIP_SET* set, /**< global SCIP settings */
555  SCIP_STAT* stat, /**< problem statistics */
556  SCIP_LP* lp, /**< current LP data */
557  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
558  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
559  int depth, /**< depth in the tree, where the bound change takes place */
560  int pos, /**< position of the bound change in its bound change array */
561  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
562  )
563 {
564  SCIP_VAR* var;
565 
566  assert(boundchg != NULL);
567  assert(stat != NULL);
568  assert(depth > 0);
569  assert(pos >= 0);
570  assert(cutoff != NULL);
571 
572  *cutoff = FALSE;
573 
574  /* ignore redundant bound changes */
575  if( boundchg->redundant )
576  return SCIP_OKAY;
577 
578  var = boundchg->var;
579  assert(var != NULL);
581  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
582 
583  /* apply bound change */
584  switch( boundchg->boundtype )
585  {
587  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
588  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
589  {
590  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
591  {
592  /* add the bound change info to the variable's bound change info array */
593  switch( boundchg->boundchgtype )
594  {
596  SCIPdebugMessage(" -> branching: new lower bound of <%s>[%g,%g]: %g\n",
597  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
598  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
600  stat->lastbranchvar = var;
602  stat->lastbranchvalue = boundchg->newbound;
603  break;
604 
606  assert(boundchg->data.inferencedata.reason.cons != NULL);
607  SCIPdebugMessage(" -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
608  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
609  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
610  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
611  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
612  boundchg->data.inferencedata.info,
614  break;
615 
617  SCIPdebugMessage(" -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
618  boundchg->data.inferencedata.reason.prop != NULL
619  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
620  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
621  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
622  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
623  boundchg->data.inferencedata.info,
625  break;
626 
627  default:
628  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
629  return SCIP_INVALIDDATA;
630  }
631 
632  /* change local bound of variable */
633  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
634  }
635  else
636  {
637  SCIPdebugMessage(" -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
638  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
639  *cutoff = TRUE;
640  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
641  }
642  }
643  else
644  {
645  /* mark bound change to be inactive */
646  SCIPdebugMessage(" -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
647  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
648  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
649  boundchg->redundant = TRUE;
650  }
651  break;
652 
654  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
655  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
656  {
657  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
658  {
659  /* add the bound change info to the variable's bound change info array */
660  switch( boundchg->boundchgtype )
661  {
663  SCIPdebugMessage(" -> branching: new upper bound of <%s>[%g,%g]: %g\n",
664  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
665  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
667  stat->lastbranchvar = var;
669  stat->lastbranchvalue = boundchg->newbound;
670  break;
671 
673  assert(boundchg->data.inferencedata.reason.cons != NULL);
674  SCIPdebugMessage(" -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
675  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
676  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
677  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
678  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
679  boundchg->data.inferencedata.info,
681  break;
682 
684  SCIPdebugMessage(" -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
685  boundchg->data.inferencedata.reason.prop != NULL
686  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
687  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
688  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
689  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
690  boundchg->data.inferencedata.info,
692  break;
693 
694  default:
695  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
696  return SCIP_INVALIDDATA;
697  }
698 
699  /* change local bound of variable */
700  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
701  }
702  else
703  {
704  SCIPdebugMessage(" -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
705  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
706  *cutoff = TRUE;
707  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
708  }
709  }
710  else
711  {
712  /* mark bound change to be inactive */
713  SCIPdebugMessage(" -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
714  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
715  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
716  boundchg->redundant = TRUE;
717  }
718  break;
719 
720  default:
721  SCIPerrorMessage("unknown bound type\n");
722  return SCIP_INVALIDDATA;
723  }
724 
725  /* update the branching and inference history */
726  if( !boundchg->applied && !boundchg->redundant )
727  {
728  assert(var == boundchg->var);
729 
731  {
732  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
735  }
736  else if( stat->lastbranchvar != NULL )
737  {
738  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
739  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
740  }
741  boundchg->applied = TRUE;
742  }
743 
744  return SCIP_OKAY;
745 }
746 
747 /** undoes single bound change */
749  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
750  BMS_BLKMEM* blkmem, /**< block memory */
751  SCIP_SET* set, /**< global SCIP settings */
752  SCIP_STAT* stat, /**< problem statistics */
753  SCIP_LP* lp, /**< current LP data */
754  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
755  SCIP_EVENTQUEUE* eventqueue /**< event queue */
756  )
757 {
758  SCIP_VAR* var;
759 
760  assert(boundchg != NULL);
761  assert(stat != NULL);
762 
763  /* ignore redundant bound changes */
764  if( boundchg->redundant )
765  return SCIP_OKAY;
766 
767  var = boundchg->var;
768  assert(var != NULL);
770 
771  /* undo bound change: apply the previous bound change of variable */
772  switch( boundchg->boundtype )
773  {
775  var->nlbchginfos--;
776  assert(var->nlbchginfos >= 0);
777  assert(var->lbchginfos != NULL);
778  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
779  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
780 
781  SCIPdebugMessage("removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
782  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
785 
786  /* reinstall the previous local bound */
787  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
788  var->lbchginfos[var->nlbchginfos].oldbound) );
789 
790  /* in case all bound changes are removed the local bound should match the global bound */
791  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
792 
793  break;
794 
796  var->nubchginfos--;
797  assert(var->nubchginfos >= 0);
798  assert(var->ubchginfos != NULL);
799  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
800  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
801 
802  SCIPdebugMessage("removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
803  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
806 
807  /* reinstall the previous local bound */
808  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
809  var->ubchginfos[var->nubchginfos].oldbound) );
810 
811  /* in case all bound changes are removed the local bound should match the global bound */
812  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
813 
814  break;
815 
816  default:
817  SCIPerrorMessage("unknown bound type\n");
818  return SCIP_INVALIDDATA;
819  }
820 
821  /* update last branching variable */
823  {
824  stat->lastbranchvar = NULL;
826  }
827 
828  return SCIP_OKAY;
829 }
830 
831 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
832 static
834  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
835  BMS_BLKMEM* blkmem, /**< block memory */
836  SCIP_SET* set, /**< global SCIP settings */
837  SCIP_STAT* stat, /**< problem statistics */
838  SCIP_LP* lp, /**< current LP data */
839  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
840  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
841  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
842  )
843 {
844  SCIP_VAR* var;
845  SCIP_Real newbound;
846  SCIP_BOUNDTYPE boundtype;
847 
848  assert(boundchg != NULL);
849  assert(cutoff != NULL);
850 
851  *cutoff = FALSE;
852 
853  /* ignore redundant bound changes */
854  if( boundchg->redundant )
855  return SCIP_OKAY;
856 
857  var = SCIPboundchgGetVar(boundchg);
858  newbound = SCIPboundchgGetNewbound(boundchg);
859  boundtype = SCIPboundchgGetBoundtype(boundchg);
860 
861  /* check if the bound change is redundant which can happen due to a (better) global bound change which was perforemed
862  * after that bound change was applied
863  *
864  * @note a global bound change is not captured by the redundant member of the bound change data structure
865  */
866  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
867  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
868  {
869  return SCIP_OKAY;
870  }
871 
872  SCIPdebugMessage("applying global bound change: <%s>[%g,%g] %s %g\n",
874  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
875 
876  /* check for cutoff */
877  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
878  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
879  {
880  *cutoff = TRUE;
881  return SCIP_OKAY;
882  }
883 
884  /* apply bound change */
885  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound, boundtype) );
886 
887  return SCIP_OKAY;
888 }
889 
890 /** captures branching and inference data of bound change */
891 static
893  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
894  )
895 {
896  assert(boundchg != NULL);
897 
898  /* capture variable associated with the bound change */
899  assert(boundchg->var != NULL);
900  SCIPvarCapture(boundchg->var);
901 
902  switch( boundchg->boundchgtype )
903  {
906  break;
907 
909  assert(boundchg->data.inferencedata.var != NULL);
910  assert(boundchg->data.inferencedata.reason.cons != NULL);
911  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
912  break;
913 
914  default:
915  SCIPerrorMessage("invalid bound change type\n");
916  return SCIP_INVALIDDATA;
917  }
918 
919  return SCIP_OKAY;
920 }
921 
922 /** releases branching and inference data of bound change */
923 static
925  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
926  BMS_BLKMEM* blkmem, /**< block memory */
927  SCIP_SET* set, /**< global SCIP settings */
928  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
929  SCIP_LP* lp /**< current LP data */
930 
931  )
932 {
933  assert(boundchg != NULL);
934 
935  switch( boundchg->boundchgtype )
936  {
939  break;
940 
942  assert(boundchg->data.inferencedata.var != NULL);
943  assert(boundchg->data.inferencedata.reason.cons != NULL);
944  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
945  break;
946 
947  default:
948  SCIPerrorMessage("invalid bound change type\n");
949  return SCIP_INVALIDDATA;
950  }
951 
952  /* release variable */
953  assert(boundchg->var != NULL);
954  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
955 
956 
957  return SCIP_OKAY;
958 }
959 
960 /** creates empty domain change data with dynamic arrays */
961 static
963  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
964  BMS_BLKMEM* blkmem /**< block memory */
965  )
966 {
967  assert(domchg != NULL);
968  assert(blkmem != NULL);
969 
970  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
971  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
972  (*domchg)->domchgdyn.nboundchgs = 0;
973  (*domchg)->domchgdyn.boundchgs = NULL;
974  (*domchg)->domchgdyn.nholechgs = 0;
975  (*domchg)->domchgdyn.holechgs = NULL;
976  (*domchg)->domchgdyn.boundchgssize = 0;
977  (*domchg)->domchgdyn.holechgssize = 0;
978 
979  return SCIP_OKAY;
980 }
981 
982 /** frees domain change data */
984  SCIP_DOMCHG** domchg, /**< pointer to domain change */
985  BMS_BLKMEM* blkmem, /**< block memory */
986  SCIP_SET* set, /**< global SCIP settings */
987  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
988  SCIP_LP* lp /**< current LP data */
989  )
990 {
991  assert(domchg != NULL);
992  assert(blkmem != NULL);
993 
994  if( *domchg != NULL )
995  {
996  int i;
997 
998  /* release variables, branching and inference data associated with the bound changes */
999  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1000  {
1001  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1002  }
1003 
1004  /* free memory for bound and hole changes */
1005  switch( (*domchg)->domchgdyn.domchgtype )
1006  {
1007  case SCIP_DOMCHGTYPE_BOUND:
1008  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1009  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1010  break;
1011  case SCIP_DOMCHGTYPE_BOTH:
1012  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1013  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1014  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1015  break;
1017  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1018  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1019  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1020  break;
1021  default:
1022  SCIPerrorMessage("invalid domain change type\n");
1023  return SCIP_INVALIDDATA;
1024  }
1025  }
1026 
1027  return SCIP_OKAY;
1028 }
1029 
1030 /** converts a static domain change data into a dynamic one */
1031 static
1033  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1034  BMS_BLKMEM* blkmem /**< block memory */
1035  )
1036 {
1037  assert(domchg != NULL);
1038  assert(blkmem != NULL);
1039 
1040  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1041 
1042  if( *domchg == NULL )
1043  {
1044  SCIP_CALL( domchgCreate(domchg, blkmem) );
1045  }
1046  else
1047  {
1048  switch( (*domchg)->domchgdyn.domchgtype )
1049  {
1050  case SCIP_DOMCHGTYPE_BOUND:
1051  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1052  (*domchg)->domchgdyn.nholechgs = 0;
1053  (*domchg)->domchgdyn.holechgs = NULL;
1054  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1055  (*domchg)->domchgdyn.holechgssize = 0;
1056  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1057  break;
1058  case SCIP_DOMCHGTYPE_BOTH:
1059  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1060  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1061  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1062  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1063  break;
1065  break;
1066  default:
1067  SCIPerrorMessage("invalid domain change type\n");
1068  return SCIP_INVALIDDATA;
1069  }
1070  }
1071 #ifndef NDEBUG
1072  {
1073  int i;
1074  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1075  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1076  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1077  }
1078 #endif
1079 
1080  return SCIP_OKAY;
1081 }
1082 
1083 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1085  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1086  BMS_BLKMEM* blkmem, /**< block memory */
1087  SCIP_SET* set, /**< global SCIP settings */
1088  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1089  SCIP_LP* lp /**< current LP data */
1090  )
1091 {
1092  assert(domchg != NULL);
1093  assert(blkmem != NULL);
1094 
1095  SCIPdebugMessage("making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1096 
1097  if( *domchg != NULL )
1098  {
1099  switch( (*domchg)->domchgdyn.domchgtype )
1100  {
1101  case SCIP_DOMCHGTYPE_BOUND:
1102  if( (*domchg)->domchgbound.nboundchgs == 0 )
1103  {
1104  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1105  }
1106  break;
1107  case SCIP_DOMCHGTYPE_BOTH:
1108  if( (*domchg)->domchgboth.nholechgs == 0 )
1109  {
1110  if( (*domchg)->domchgbound.nboundchgs == 0 )
1111  {
1112  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1113  }
1114  else
1115  {
1116  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1117  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1118  }
1119  }
1120  break;
1122  if( (*domchg)->domchgboth.nholechgs == 0 )
1123  {
1124  if( (*domchg)->domchgbound.nboundchgs == 0 )
1125  {
1126  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1127  }
1128  else
1129  {
1130  /* shrink dynamic size arrays to their minimal sizes */
1131  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1132  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1133  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1134 
1135  /* convert into static domain change */
1136  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1137  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1138  }
1139  }
1140  else
1141  {
1142  /* shrink dynamic size arrays to their minimal sizes */
1143  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1144  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1145  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs,
1146  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1147 
1148  /* convert into static domain change */
1149  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1150  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1151  }
1152  break;
1153  default:
1154  SCIPerrorMessage("invalid domain change type\n");
1155  return SCIP_INVALIDDATA;
1156  }
1157 #ifndef NDEBUG
1158  if( *domchg != NULL )
1159  {
1160  int i;
1161  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1162  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1163  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1164  }
1165 #endif
1166  }
1167 
1168  return SCIP_OKAY;
1169 }
1170 
1171 /** ensures, that boundchgs array can store at least num entries */
1172 static
1174  SCIP_DOMCHG* domchg, /**< domain change data structure */
1175  BMS_BLKMEM* blkmem, /**< block memory */
1176  SCIP_SET* set, /**< global SCIP settings */
1177  int num /**< minimum number of entries to store */
1178  )
1179 {
1180  assert(domchg != NULL);
1181  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1182 
1183  if( num > domchg->domchgdyn.boundchgssize )
1184  {
1185  int newsize;
1186 
1187  newsize = SCIPsetCalcMemGrowSize(set, num);
1188  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1189  domchg->domchgdyn.boundchgssize = newsize;
1190  }
1191  assert(num <= domchg->domchgdyn.boundchgssize);
1192 
1193  return SCIP_OKAY;
1194 }
1195 
1196 /** ensures, that holechgs array can store at least num additional entries */
1197 static
1199  SCIP_DOMCHG* domchg, /**< domain change data structure */
1200  BMS_BLKMEM* blkmem, /**< block memory */
1201  SCIP_SET* set, /**< global SCIP settings */
1202  int num /**< minimum number of additional entries to store */
1203  )
1204 {
1205  assert(domchg != NULL);
1206  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1207 
1208  if( num > domchg->domchgdyn.holechgssize )
1209  {
1210  int newsize;
1211 
1212  newsize = SCIPsetCalcMemGrowSize(set, num);
1213  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1214  domchg->domchgdyn.holechgssize = newsize;
1215  }
1216  assert(num <= domchg->domchgdyn.holechgssize);
1217 
1218  return SCIP_OKAY;
1219 }
1220 
1221 /** applies domain change */
1223  SCIP_DOMCHG* domchg, /**< domain change to apply */
1224  BMS_BLKMEM* blkmem, /**< block memory */
1225  SCIP_SET* set, /**< global SCIP settings */
1226  SCIP_STAT* stat, /**< problem statistics */
1227  SCIP_LP* lp, /**< current LP data */
1228  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1229  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1230  int depth, /**< depth in the tree, where the domain change takes place */
1231  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1232  )
1233 {
1234  int i;
1235 
1236  assert(cutoff != NULL);
1237 
1238  *cutoff = FALSE;
1239 
1240  SCIPdebugMessage("applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1241 
1242  if( domchg == NULL )
1243  return SCIP_OKAY;
1244 
1245  /* apply bound changes */
1246  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1247  {
1248  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1249  branchcand, eventqueue, depth, i, cutoff) );
1250  if( *cutoff )
1251  break;
1252  }
1253  SCIPdebugMessage(" -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1254 
1255  /* mark all bound changes after a cutoff redundant */
1256  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1257  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1258 
1259  /* apply holelist changes */
1260  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1261  {
1262  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1263  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1264  SCIPdebugMessage(" -> %d hole changes\n", domchg->domchgboth.nholechgs);
1265  }
1266 
1267  return SCIP_OKAY;
1268 }
1269 
1270 /** undoes domain change */
1272  SCIP_DOMCHG* domchg, /**< domain change to remove */
1273  BMS_BLKMEM* blkmem, /**< block memory */
1274  SCIP_SET* set, /**< global SCIP settings */
1275  SCIP_STAT* stat, /**< problem statistics */
1276  SCIP_LP* lp, /**< current LP data */
1277  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1278  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1279  )
1280 {
1281  int i;
1282 
1283  SCIPdebugMessage("undoing domain changes at %p\n", (void*)domchg);
1284  if( domchg == NULL )
1285  return SCIP_OKAY;
1286 
1287  /* undo holelist changes */
1288  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1289  {
1290  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1291  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1292  SCIPdebugMessage(" -> %d hole changes\n", domchg->domchgboth.nholechgs);
1293  }
1294 
1295  /* undo bound changes */
1296  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1297  {
1298  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1299  }
1300  SCIPdebugMessage(" -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1301 
1302  return SCIP_OKAY;
1303 }
1304 
1305 /** applies domain change to the global problem */
1307  SCIP_DOMCHG* domchg, /**< domain change to apply */
1308  BMS_BLKMEM* blkmem, /**< block memory */
1309  SCIP_SET* set, /**< global SCIP settings */
1310  SCIP_STAT* stat, /**< problem statistics */
1311  SCIP_LP* lp, /**< current LP data */
1312  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1313  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1314  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1315  )
1316 {
1317  int i;
1318 
1319  assert(cutoff != NULL);
1320 
1321  *cutoff = FALSE;
1322 
1323  if( domchg == NULL )
1324  return SCIP_OKAY;
1325 
1326  SCIPdebugMessage("applying domain changes at %p to the global problem\n", (void*)domchg);
1327 
1328  /* apply bound changes */
1329  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1330  {
1331  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1332  branchcand, eventqueue, cutoff) );
1333  if( *cutoff )
1334  break;
1335  }
1336  SCIPdebugMessage(" -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1337 
1338  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1339 
1340  return SCIP_OKAY;
1341 }
1342 
1343 /** adds bound change to domain changes */
1345  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1346  BMS_BLKMEM* blkmem, /**< block memory */
1347  SCIP_SET* set, /**< global SCIP settings */
1348  SCIP_VAR* var, /**< variable to change the bounds for */
1349  SCIP_Real newbound, /**< new value for bound */
1350  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1351  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1352  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1353  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1354  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1355  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1356  int inferinfo, /**< user information for inference to help resolving the conflict */
1357  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1358  )
1359 {
1360  SCIP_BOUNDCHG* boundchg;
1361 
1362  assert(domchg != NULL);
1363  assert(var != NULL);
1365  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1366  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1367  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1368  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1369  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1370 
1371  SCIPdebugMessage("adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1372  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper",
1373  boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1374  newbound, var->name, (void*)domchg, (void*)*domchg);
1375 
1376  /* if domain change data doesn't exist, create it;
1377  * if domain change is static, convert it into dynamic change
1378  */
1379  if( *domchg == NULL )
1380  {
1381  SCIP_CALL( domchgCreate(domchg, blkmem) );
1382  }
1383  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1384  {
1385  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1386  }
1387  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1388 
1389  /* get memory for additional bound change */
1390  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1391 
1392  /* fill in the bound change data */
1393  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1394  boundchg->var = var;
1395  switch( boundchgtype )
1396  {
1398  boundchg->data.branchingdata.lpsolval = lpsolval;
1399  break;
1401  assert(infercons != NULL);
1402  boundchg->data.inferencedata.var = infervar;
1403  boundchg->data.inferencedata.reason.cons = infercons;
1404  boundchg->data.inferencedata.info = inferinfo;
1405  break;
1407  boundchg->data.inferencedata.var = infervar;
1408  boundchg->data.inferencedata.reason.prop = inferprop;
1409  boundchg->data.inferencedata.info = inferinfo;
1410  break;
1411  default:
1412  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1413  return SCIP_INVALIDDATA;
1414  }
1415 
1416  boundchg->newbound = newbound;
1417  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1418  boundchg->boundtype = boundtype; /*lint !e641*/
1419  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1420  boundchg->applied = FALSE;
1421  boundchg->redundant = FALSE;
1422  (*domchg)->domchgdyn.nboundchgs++;
1423 
1424  /* capture branching and inference data associated with the bound changes */
1425  SCIP_CALL( boundchgCaptureData(boundchg) );
1426 
1427 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1428 #ifdef SCIP_MORE_DEBUG
1429  {
1430  int i;
1431  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1432  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1433  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1434  }
1435 #endif
1436 #endif
1437 
1438  return SCIP_OKAY;
1439 }
1440 
1441 /** adds hole change to domain changes */
1443  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1444  BMS_BLKMEM* blkmem, /**< block memory */
1445  SCIP_SET* set, /**< global SCIP settings */
1446  SCIP_HOLELIST** ptr, /**< changed list pointer */
1447  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1448  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1449  )
1450 {
1451  SCIP_HOLECHG* holechg;
1452 
1453  assert(domchg != NULL);
1454  assert(ptr != NULL);
1455 
1456  /* if domain change data doesn't exist, create it;
1457  * if domain change is static, convert it into dynamic change
1458  */
1459  if( *domchg == NULL )
1460  {
1461  SCIP_CALL( domchgCreate(domchg, blkmem) );
1462  }
1463  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1464  {
1465  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1466  }
1467  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1468 
1469  /* get memory for additional hole change */
1470  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1471 
1472  /* fill in the hole change data */
1473  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1474  holechg->ptr = ptr;
1475  holechg->newlist = newlist;
1476  holechg->oldlist = oldlist;
1477  (*domchg)->domchgdyn.nholechgs++;
1478 
1479  return SCIP_OKAY;
1480 }
1481 
1482 
1483 
1484 
1485 /*
1486  * methods for variables
1487  */
1488 
1489 /** returns adjusted lower bound value, which is rounded for integral variable types */
1490 static
1492  SCIP_SET* set, /**< global SCIP settings */
1493  SCIP_VARTYPE vartype, /**< type of variable */
1494  SCIP_Real lb /**< lower bound to adjust */
1495  )
1496 {
1497  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1498  return -SCIPsetInfinity(set);
1499  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1500  return SCIPsetInfinity(set);
1501  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1502  return SCIPsetFeasCeil(set, lb);
1503  else if( SCIPsetIsZero(set, lb) )
1504  return 0.0;
1505  else
1506  return lb;
1507 }
1508 
1509 /** returns adjusted upper bound value, which is rounded for integral variable types */
1510 static
1512  SCIP_SET* set, /**< global SCIP settings */
1513  SCIP_VARTYPE vartype, /**< type of variable */
1514  SCIP_Real ub /**< upper bound to adjust */
1515  )
1516 {
1517  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1518  return SCIPsetInfinity(set);
1519  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1520  return -SCIPsetInfinity(set);
1521  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1522  return SCIPsetFeasFloor(set, ub);
1523  else if( SCIPsetIsZero(set, ub) )
1524  return 0.0;
1525  else
1526  return ub;
1527 }
1528 
1529 /* removes (redundant) implications and variable bounds of variable from all other variables' implications and variable
1530  * bounds arrays, and optionally removes them also from the variable itself
1531  */
1532 static
1534  SCIP_VAR* var, /**< problem variable */
1535  BMS_BLKMEM* blkmem, /**< block memory */
1536  SCIP_SET* set, /**< global SCIP settings */
1537  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1538  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1539  )
1540 {
1541  SCIP_Real lb;
1542  SCIP_Real ub;
1543 
1544  assert(var != NULL);
1546  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1547 
1548  lb = SCIPvarGetLbGlobal(var);
1549  ub = SCIPvarGetUbGlobal(var);
1550 
1551  SCIPdebugMessage("removing %s implications and vbounds of <%s>[%g,%g]\n",
1552  onlyredundant ? "redundant" : "all", SCIPvarGetName(var), lb, ub);
1553 
1554  /* remove implications of (fixed) binary variable */
1555  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1556  {
1557  SCIP_Bool varfixing;
1558 
1559  assert(SCIPvarIsBinary(var));
1560 
1561  varfixing = FALSE;
1562  do
1563  {
1564  int nimpls;
1565  int nbinimpls;
1566  SCIP_VAR** implvars;
1567  SCIP_BOUNDTYPE* impltypes;
1568  int i;
1569 
1570  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1571  nbinimpls = SCIPimplicsGetNBinImpls(var->implics, varfixing);
1572  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1573  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1574 
1575  /* process the implications on binary variables */
1576  for( i = 0; i < nbinimpls; i++ )
1577  {
1578  SCIP_VAR* implvar;
1579  SCIP_BOUNDTYPE impltype;
1580 
1581  implvar = implvars[i];
1582  impltype = impltypes[i];
1583  assert(implvar != var);
1584  assert(SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY);
1585 
1586  /* remove for all implications z == 0 / 1 ==> x <= 0 / x >= 1 (x binary)
1587  * the following implication from x's implications
1588  * x == 1 ==> z <= 0 , for z == 1 ==> x <= 0
1589  * x == 0 ==> z <= 0 , for z == 1 ==> x >= 1
1590  *
1591  * x == 1 ==> z >= 1 , for z == 0 ==> x <= 0
1592  * x == 0 ==> z >= 1 , for z == 0 ==> x >= 1
1593  */
1594  if( implvar->implics != NULL ) /* implvar may have been aggregated in the mean time */
1595  {
1596  SCIPdebugMessage("deleting implication: <%s> == %d ==> <%s> %s\n",
1597  SCIPvarGetName(implvar), (impltype == SCIP_BOUNDTYPE_UPPER),
1598  SCIPvarGetName(var), varfixing ? "<= 0 " : ">= 1");
1599  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (impltype == SCIP_BOUNDTYPE_UPPER), var,
1600  varfixing ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER) );
1601  }
1602  }
1603 
1604  /* process the implications on non-binary variables */
1605  for( i = nbinimpls; i < nimpls; i++ )
1606  {
1607  SCIP_VAR* implvar;
1608  SCIP_BOUNDTYPE impltype;
1609 
1610  implvar = implvars[i];
1611  impltype = impltypes[i];
1612  assert(implvar != var);
1613  assert(SCIPvarGetType(implvar) != SCIP_VARTYPE_BINARY);
1614 
1615  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1616  * the following variable bound from x's variable bounds
1617  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1618  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1619  */
1620  if( impltype == SCIP_BOUNDTYPE_UPPER )
1621  {
1622  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1623  {
1624  SCIPdebugMessage("deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1625  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1626  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1627  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1628  implvar->closestvblpcount = -1;
1629  var->closestvblpcount = -1;
1630  }
1631  }
1632  else
1633  {
1634  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1635  {
1636  SCIPdebugMessage("deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1637  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1638  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1639  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1640  implvar->closestvblpcount = -1;
1641  var->closestvblpcount = -1;
1642  }
1643  }
1644  }
1645  varfixing = !varfixing;
1646  }
1647  while( varfixing == TRUE );
1648 
1649  if( removefromvar )
1650  {
1651  /* free the implications data structures */
1652  SCIPimplicsFree(&var->implics, blkmem);
1653  }
1654  }
1655 
1656  /* remove the (redundant) variable lower bounds */
1657  if( var->vlbs != NULL )
1658  {
1659  SCIP_VAR** vars;
1660  SCIP_Real* coefs;
1661  SCIP_Real* constants;
1662  int nvbds;
1663  int newnvbds;
1664  int i;
1665 
1666  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1667  vars = SCIPvboundsGetVars(var->vlbs);
1668  coefs = SCIPvboundsGetCoefs(var->vlbs);
1669  constants = SCIPvboundsGetConstants(var->vlbs);
1670 
1671  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1672  * z == ub ==> x >= b*ub + d , if b > 0
1673  * z == lb ==> x >= b*lb + d , if b < 0
1674  */
1675  newnvbds = 0;
1676  for( i = 0; i < nvbds; i++ )
1677  {
1678  SCIP_VAR* implvar;
1679  SCIP_Real coef;
1680 
1681  assert(newnvbds <= i);
1682 
1683  implvar = vars[i];
1684  assert(implvar != NULL);
1685 
1686  coef = coefs[i];
1687  assert(!SCIPsetIsZero(set, coef));
1688 
1689  /* check, if we want to remove the variable bound */
1690  if( onlyredundant )
1691  {
1692  SCIP_Real vbound;
1693 
1694  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1695  if( SCIPsetIsFeasGT(set, vbound, lb) )
1696  {
1697  /* the variable bound is not redundant: keep it */
1698  if( removefromvar )
1699  {
1700  if( newnvbds < i )
1701  {
1702  vars[newnvbds] = implvar;
1703  coefs[newnvbds] = coef;
1704  constants[newnvbds] = constants[i];
1705  }
1706  newnvbds++;
1707  }
1708  continue;
1709  }
1710  }
1711 
1712  /* remove the corresponding implication */
1713  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1714  {
1715  SCIPdebugMessage("deleting implication: <%s> == %d ==> <%s> >= %g\n",
1716  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1717  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1718  }
1719  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1720  {
1721  SCIPdebugMessage("deleting variable upper bound from <%s> involving variable %s\n",
1722  SCIPvarGetName(implvar), SCIPvarGetName(var));
1723  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1724  implvar->closestvblpcount = -1;
1725  var->closestvblpcount = -1;
1726  }
1727  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1728  {
1729  SCIPdebugMessage("deleting variable lower bound from <%s> involving variable %s\n",
1730  SCIPvarGetName(implvar), SCIPvarGetName(var));
1731  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1732  implvar->closestvblpcount = -1;
1733  var->closestvblpcount = -1;
1734  }
1735  }
1736 
1737  if( removefromvar )
1738  {
1739  /* update the number of variable bounds */
1740  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1741  var->closestvblpcount = -1;
1742  }
1743  }
1744 
1745  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1746  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1747  * cannot remove such variables x from z's implications.
1748  */
1749 
1750  /* remove the (redundant) variable upper bounds */
1751  if( var->vubs != NULL )
1752  {
1753  SCIP_VAR** vars;
1754  SCIP_Real* coefs;
1755  SCIP_Real* constants;
1756  int nvbds;
1757  int newnvbds;
1758  int i;
1759 
1760  nvbds = SCIPvboundsGetNVbds(var->vubs);
1761  vars = SCIPvboundsGetVars(var->vubs);
1762  coefs = SCIPvboundsGetCoefs(var->vubs);
1763  constants = SCIPvboundsGetConstants(var->vubs);
1764 
1765  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1766  * z == lb ==> x <= b*lb + d , if b > 0
1767  * z == ub ==> x <= b*ub + d , if b < 0
1768  */
1769  newnvbds = 0;
1770  for( i = 0; i < nvbds; i++ )
1771  {
1772  SCIP_VAR* implvar;
1773  SCIP_Real coef;
1774 
1775  assert(newnvbds <= i);
1776 
1777  implvar = vars[i];
1778  assert(implvar != NULL);
1779 
1780  coef = coefs[i];
1781  assert(!SCIPsetIsZero(set, coef));
1782 
1783  /* check, if we want to remove the variable bound */
1784  if( onlyredundant )
1785  {
1786  SCIP_Real vbound;
1787 
1788  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1789  if( SCIPsetIsFeasLT(set, vbound, ub) )
1790  {
1791  /* the variable bound is not redundant: keep it */
1792  if( removefromvar )
1793  {
1794  if( newnvbds < i )
1795  {
1796  vars[newnvbds] = implvar;
1797  coefs[newnvbds] = coefs[i];
1798  constants[newnvbds] = constants[i];
1799  }
1800  newnvbds++;
1801  }
1802  continue;
1803  }
1804  }
1805 
1806  /* remove the corresponding implication */
1807  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1808  {
1809  SCIPdebugMessage("deleting implication: <%s> == %d ==> <%s> <= %g\n",
1810  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1811  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1812  }
1813  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1814  {
1815  SCIPdebugMessage("deleting variable upper bound from <%s> involving variable %s\n",
1816  SCIPvarGetName(implvar), SCIPvarGetName(var));
1817  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1818  implvar->closestvblpcount = -1;
1819  var->closestvblpcount = -1;
1820  }
1821  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1822  {
1823  SCIPdebugMessage("deleting variable lower bound from <%s> involving variable %s\n",
1824  SCIPvarGetName(implvar), SCIPvarGetName(var));
1825  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1826  implvar->closestvblpcount = -1;
1827  var->closestvblpcount = -1;
1828  }
1829  }
1830 
1831  if( removefromvar )
1832  {
1833  /* update the number of variable bounds */
1834  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1835  var->closestvblpcount = -1;
1836  }
1837  }
1838 
1839  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1840  * z has no link (like in the binary case) to x
1841  */
1842 
1843  return SCIP_OKAY;
1844 }
1845 
1846 /** sets the variable name */
1847 static
1849  SCIP_VAR* var, /**< problem variable */
1850  BMS_BLKMEM* blkmem, /**< block memory */
1851  SCIP_STAT* stat, /**< problem statistics, or NULL */
1852  const char* name /**< name of variable, or NULL for automatic name creation */
1853  )
1854 {
1855  assert(blkmem != NULL);
1856  assert(var != NULL);
1857 
1858  if( name == NULL )
1859  {
1860  char s[SCIP_MAXSTRLEN];
1861 
1862  assert(stat != NULL);
1863 
1864  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1865  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1866  }
1867  else
1868  {
1869  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1870  }
1871 
1872  return SCIP_OKAY;
1873 }
1874 
1875 
1876 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1877  * with bounds zero and one is automatically converted into a binary variable
1878  */
1879 static
1881  SCIP_VAR** var, /**< pointer to variable data */
1882  BMS_BLKMEM* blkmem, /**< block memory */
1883  SCIP_SET* set, /**< global SCIP settings */
1884  SCIP_STAT* stat, /**< problem statistics */
1885  const char* name, /**< name of variable, or NULL for automatic name creation */
1886  SCIP_Real lb, /**< lower bound of variable */
1887  SCIP_Real ub, /**< upper bound of variable */
1888  SCIP_Real obj, /**< objective function value */
1889  SCIP_VARTYPE vartype, /**< type of variable */
1890  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1891  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1892  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1893  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1894  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1895  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1896  SCIP_VARDATA* vardata /**< user data for this specific variable */
1897  )
1898 {
1899  assert(var != NULL);
1900  assert(blkmem != NULL);
1901  assert(stat != NULL);
1902 
1903  /* adjust bounds of variable */
1904  lb = adjustedLb(set, vartype, lb);
1905  ub = adjustedUb(set, vartype, ub);
1906 
1907  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1908  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1909  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1910  {
1911  if( vartype == SCIP_VARTYPE_INTEGER )
1912  vartype = SCIP_VARTYPE_BINARY;
1913  }
1914  else
1915  {
1916  if( vartype == SCIP_VARTYPE_BINARY )
1917  {
1918  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1919  return SCIP_INVALIDDATA;
1920  }
1921  }
1922 
1923  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1924  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1925 
1926  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1927 
1928  /* set variable's name */
1929  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1930 
1931 #ifndef NDEBUG
1932  (*var)->scip = set->scip;
1933 #endif
1934  (*var)->obj = obj;
1935  (*var)->branchfactor = 1.0;
1936  (*var)->rootsol = 0.0;
1937  (*var)->bestrootsol = 0.0;
1938  (*var)->bestrootredcost = 0.0;
1939  (*var)->bestrootlpobjval = SCIP_INVALID;
1940  (*var)->relaxsol = 0.0;
1941  (*var)->nlpsol = 0.0;
1942  (*var)->primsolavg = 0.5 * (lb + ub);
1943  (*var)->conflictlb = SCIP_REAL_MIN;
1944  (*var)->conflictub = SCIP_REAL_MAX;
1945  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1946  (*var)->conflictrelaxedub = (*var)->conflictub;
1947  (*var)->lazylb = -SCIPsetInfinity(set);
1948  (*var)->lazyub = SCIPsetInfinity(set);
1949  (*var)->glbdom.holelist = NULL;
1950  (*var)->glbdom.lb = lb;
1951  (*var)->glbdom.ub = ub;
1952  (*var)->locdom.holelist = NULL;
1953  (*var)->locdom.lb = lb;
1954  (*var)->locdom.ub = ub;
1955  (*var)->varcopy = varcopy;
1956  (*var)->vardelorig = vardelorig;
1957  (*var)->vartrans = vartrans;
1958  (*var)->vardeltrans = vardeltrans;
1959  (*var)->vardata = vardata;
1960  (*var)->parentvars = NULL;
1961  (*var)->negatedvar = NULL;
1962  (*var)->vlbs = NULL;
1963  (*var)->vubs = NULL;
1964  (*var)->implics = NULL;
1965  (*var)->cliquelist = NULL;
1966  (*var)->eventfilter = NULL;
1967  (*var)->lbchginfos = NULL;
1968  (*var)->ubchginfos = NULL;
1969  (*var)->index = stat->nvaridx;
1970  (*var)->probindex = -1;
1971  (*var)->pseudocandindex = -1;
1972  (*var)->eventqueueindexobj = -1;
1973  (*var)->eventqueueindexlb = -1;
1974  (*var)->eventqueueindexub = -1;
1975  (*var)->parentvarssize = 0;
1976  (*var)->nparentvars = 0;
1977  (*var)->nuses = 0;
1978  (*var)->nlocksdown = 0;
1979  (*var)->nlocksup = 0;
1980  (*var)->branchpriority = 0;
1981  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1982  (*var)->lbchginfossize = 0;
1983  (*var)->nlbchginfos = 0;
1984  (*var)->ubchginfossize = 0;
1985  (*var)->nubchginfos = 0;
1986  (*var)->conflictlbcount = 0;
1987  (*var)->conflictubcount = 0;
1988  (*var)->closestvlbidx = -1;
1989  (*var)->closestvubidx = -1;
1990  (*var)->closestvblpcount = -1;
1991  (*var)->initial = initial;
1992  (*var)->removable = removable;
1993  (*var)->deleted = FALSE;
1994  (*var)->donotmultaggr = FALSE;
1995  (*var)->vartype = vartype; /*lint !e641*/
1996  (*var)->pseudocostflag = FALSE;
1997  (*var)->eventqueueimpl = FALSE;
1998  (*var)->deletable = FALSE;
1999  stat->nvaridx++;
2000 
2001  /* create branching and inference history entries */
2002  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
2003  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
2004 
2005  /* the value based history is only created on demand */
2006  (*var)->valuehistory = NULL;
2007 
2008  return SCIP_OKAY;
2009 }
2010 
2011 /** creates and captures an original problem variable; an integer variable with bounds
2012  * zero and one is automatically converted into a binary variable
2013  */
2015  SCIP_VAR** var, /**< pointer to variable data */
2016  BMS_BLKMEM* blkmem, /**< block memory */
2017  SCIP_SET* set, /**< global SCIP settings */
2018  SCIP_STAT* stat, /**< problem statistics */
2019  const char* name, /**< name of variable, or NULL for automatic name creation */
2020  SCIP_Real lb, /**< lower bound of variable */
2021  SCIP_Real ub, /**< upper bound of variable */
2022  SCIP_Real obj, /**< objective function value */
2023  SCIP_VARTYPE vartype, /**< type of variable */
2024  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2025  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2026  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2027  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2028  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2029  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2030  SCIP_VARDATA* vardata /**< user data for this specific variable */
2031  )
2032 {
2033  assert(var != NULL);
2034  assert(blkmem != NULL);
2035  assert(stat != NULL);
2036 
2037  /* create variable */
2038  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2039  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2040 
2041  /* set variable status and data */
2042  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2043  (*var)->data.original.origdom.holelist = NULL;
2044  (*var)->data.original.origdom.lb = lb;
2045  (*var)->data.original.origdom.ub = ub;
2046  (*var)->data.original.transvar = NULL;
2047 
2048  /* capture variable */
2049  SCIPvarCapture(*var);
2050 
2051  return SCIP_OKAY;
2052 }
2053 
2054 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2055  * zero and one is automatically converted into a binary variable
2056  */
2058  SCIP_VAR** var, /**< pointer to variable data */
2059  BMS_BLKMEM* blkmem, /**< block memory */
2060  SCIP_SET* set, /**< global SCIP settings */
2061  SCIP_STAT* stat, /**< problem statistics */
2062  const char* name, /**< name of variable, or NULL for automatic name creation */
2063  SCIP_Real lb, /**< lower bound of variable */
2064  SCIP_Real ub, /**< upper bound of variable */
2065  SCIP_Real obj, /**< objective function value */
2066  SCIP_VARTYPE vartype, /**< type of variable */
2067  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2068  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2069  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2070  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2071  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2072  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2073  SCIP_VARDATA* vardata /**< user data for this specific variable */
2074  )
2075 {
2076  assert(var != NULL);
2077  assert(blkmem != NULL);
2078 
2079  /* create variable */
2080  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2081  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2082 
2083  /* create event filter for transformed variable */
2084  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2085 
2086  /* set variable status and data */
2087  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2088 
2089  /* capture variable */
2090  SCIPvarCapture(*var);
2091 
2092  return SCIP_OKAY;
2093 }
2094 
2095 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2096  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2097  * copied at all
2098  */
2100  SCIP_VAR** var, /**< pointer to store the target variable */
2101  BMS_BLKMEM* blkmem, /**< block memory */
2102  SCIP_SET* set, /**< global SCIP settings */
2103  SCIP_STAT* stat, /**< problem statistics */
2104  SCIP* sourcescip, /**< source SCIP data structure */
2105  SCIP_VAR* sourcevar, /**< source variable */
2106  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2107  * target variables */
2108  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2109  * target constraints */
2110  SCIP_Bool global /**< should global or local bounds be used? */
2111  )
2112 {
2113  SCIP_VARDATA* targetdata;
2114  SCIP_RESULT result;
2115  SCIP_Real lb;
2116  SCIP_Real ub;
2117 
2118  assert(set != NULL);
2119  assert(blkmem != NULL);
2120  assert(stat != NULL);
2121  assert(sourcescip != NULL);
2122  assert(sourcevar != NULL);
2123  assert(var != NULL);
2124  assert(set->stage == SCIP_STAGE_PROBLEM);
2125  assert(varmap != NULL);
2126  assert(consmap != NULL);
2127 
2128  /** @todo copy hole lists */
2129  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2130  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2131 
2132  result = SCIP_DIDNOTRUN;
2133  targetdata = NULL;
2134 
2135  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2136  {
2137  lb = SCIPvarGetLbOriginal(sourcevar);
2138  ub = SCIPvarGetUbOriginal(sourcevar);
2139  }
2140  else
2141  {
2142  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2143  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2144  }
2145 
2146  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2147  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2148  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2149  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2150  NULL, NULL, NULL, NULL, NULL) );
2151  assert(*var != NULL);
2152 
2153  /* insert variable into mapping between source SCIP and the target SCIP */
2154  assert(!SCIPhashmapExists(varmap, sourcevar));
2155  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2156 
2157  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2158  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2159  {
2160  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2161  varmap, consmap, (*var), &targetdata, &result) );
2162 
2163  /* evaluate result */
2164  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2165  {
2166  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2167  return SCIP_INVALIDRESULT;
2168  }
2169 
2170  assert(targetdata == NULL || result == SCIP_SUCCESS);
2171  }
2172 
2173  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2174  * methods
2175  */
2176  if( result == SCIP_SUCCESS )
2177  {
2178  (*var)->varcopy = sourcevar->varcopy;
2179  (*var)->vardelorig = sourcevar->vardelorig;
2180  (*var)->vartrans = sourcevar->vartrans;
2181  (*var)->vardeltrans = sourcevar->vardeltrans;
2182  (*var)->vardata = targetdata;
2183  }
2184 
2185  SCIPdebugMessage("created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2186 
2187  return SCIP_OKAY;
2188 }
2189 
2190 /** parse given string for a SCIP_Real bound */
2191 static
2193  SCIP_SET* set, /**< global SCIP settings */
2194  const char* str, /**< string to parse */
2195  SCIP_Real* value, /**< pointer to store the parsed value */
2196  char** endptr /**< pointer to store the final string position if successfully parsed */
2197  )
2198 {
2199  /* first check for infinity value */
2200  if( strncmp(str, "+inf", 4) == 0 )
2201  {
2202  *value = SCIPsetInfinity(set);
2203  (*endptr) = (char*)str + 4;
2204  }
2205  else if( strncmp(str, "-inf", 4) == 0 )
2206  {
2207  *value = -SCIPsetInfinity(set);
2208  (*endptr) = (char*)str + 4;
2209  }
2210  else
2211  {
2212  if( !SCIPstrToRealValue(str, value, endptr) )
2213  return SCIP_READERROR;
2214  }
2215 
2216  return SCIP_OKAY;
2217 }
2218 
2219 /** parse the characters as bounds */
2220 static
2222  SCIP_SET* set, /**< global SCIP settings */
2223  const char* str, /**< string to parse */
2224  char* type, /**< bound type (global, local, or lazy) */
2225  SCIP_Real* lb, /**< pointer to store the lower bound */
2226  SCIP_Real* ub, /**< pointer to store the upper bound */
2227  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2228  )
2229 {
2230  char token[SCIP_MAXSTRLEN];
2231 
2232  SCIPdebugMessage("parsing bounds: '%s'\n", str);
2233 
2234  /* get bound type */
2235  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2236  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2237  {
2238  SCIPdebugMessage("unkown bound type <%s>\n", type);
2239  *endptr = NULL;
2240  return SCIP_OKAY;
2241  }
2242 
2243  SCIPdebugMessage("parsed bound type <%s>\n", type);
2244 
2245  /* get lower bound */
2246  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2247  str = *endptr;
2248  SCIP_CALL( parseValue(set, token, lb, endptr) );
2249 
2250  /* get upper bound */
2251  SCIP_CALL( parseValue(set, str, ub, endptr) );
2252 
2253  SCIPdebugMessage("parsed bounds: [%g,%g]\n", *lb, *ub);
2254 
2255  /* skip end of bounds */
2256  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2257  ++(*endptr);
2258 
2259  return SCIP_OKAY;
2260 }
2261 
2262 /** parses a given string for a variable informations */
2263 static
2265  SCIP_SET* set, /**< global SCIP settings */
2266  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2267  const char* str, /**< string to parse */
2268  char* name, /**< pointer to store the variable name */
2269  SCIP_Real* lb, /**< pointer to store the lower bound */
2270  SCIP_Real* ub, /**< pointer to store the upper bound */
2271  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2272  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2273  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2274  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2275  SCIP_Bool local, /**< should the local bound be applied */
2276  char** endptr, /**< pointer to store the final string position if successfully */
2277  SCIP_Bool* success /**< pointer store if the paring process was successful */
2278  )
2279 {
2280  SCIP_Real parsedlb;
2281  SCIP_Real parsedub;
2282  char token[SCIP_MAXSTRLEN];
2283  char* strptr;
2284  int i;
2285 
2286  assert(lb != NULL);
2287  assert(ub != NULL);
2288  assert(obj != NULL);
2289  assert(vartype != NULL);
2290  assert(lazylb != NULL);
2291  assert(lazyub != NULL);
2292  assert(endptr != NULL);
2293  assert(success != NULL);
2294 
2295  (*success) = TRUE;
2296 
2297  /* copy variable type */
2298  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2299  assert(str != *endptr);
2300  SCIPdebugMessage("parsed variable type <%s>\n", token);
2301 
2302  /* get variable type */
2303  if( strncmp(token, "binary", 3) == 0 )
2304  (*vartype) = SCIP_VARTYPE_BINARY;
2305  else if( strncmp(token, "integer", 3) == 0 )
2306  (*vartype) = SCIP_VARTYPE_INTEGER;
2307  else if( strncmp(token, "implicit", 3) == 0 )
2308  (*vartype) = SCIP_VARTYPE_IMPLINT;
2309  else if( strncmp(token, "continuous", 3) == 0 )
2310  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2311  else
2312  {
2313  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2314  (*success) = FALSE;
2315  return SCIP_OKAY;
2316  }
2317 
2318  /* move string pointer behind variable type */
2319  str = *endptr;
2320 
2321  /* get variable name */
2322  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2323  assert(endptr != NULL);
2324  SCIPdebugMessage("parsed variable name <%s>\n", name);
2325 
2326  /* move string pointer behind variable name */
2327  str = *endptr;
2328 
2329  /* cut out objective coefficient */
2330  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2331 
2332  /* move string pointer behind objective coefficient */
2333  str = *endptr;
2334 
2335  /* get objective coefficient */
2336  if( !SCIPstrToRealValue(token, obj, endptr) )
2337  return SCIP_READERROR;
2338 
2339  SCIPdebugMessage("parsed objective coefficient <%g>\n", *obj);
2340 
2341  /* parse global/original bounds */
2342  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2343  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2344 
2345  /* initialize the lazy bound */
2346  *lazylb = -SCIPsetInfinity(set);
2347  *lazyub = SCIPsetInfinity(set);
2348 
2349  /* store pointer */
2350  strptr = *endptr;
2351 
2352  /* possibly parse optional local and lazy bounds */
2353  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2354  {
2355  /* start after previous bounds */
2356  strptr = *endptr;
2357 
2358  /* parse global bounds */
2359  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2360 
2361  if( strncmp(token, "local", 5) == 0 && local )
2362  {
2363  *lb = parsedlb;
2364  *ub = parsedub;
2365  }
2366  else if( strncmp(token, "lazy", 4) == 0 )
2367  {
2368  *lazylb = parsedlb;
2369  *lazyub = parsedub;
2370  }
2371  }
2372 
2373  /* restore pointer */
2374  if ( *endptr == NULL )
2375  *endptr = strptr;
2376 
2377  /* check bounds for binary variables */
2378  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2379  {
2380  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2381  {
2382  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2383  return SCIP_READERROR;
2384  }
2385  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2386  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2387  {
2388  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2389  return SCIP_READERROR;
2390  }
2391  }
2392 
2393  return SCIP_OKAY;
2394 }
2395 
2396 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2397  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2398  * integer variable with bounds zero and one is automatically converted into a binary variable
2399  */
2401  SCIP_VAR** var, /**< pointer to variable data */
2402  BMS_BLKMEM* blkmem, /**< block memory */
2403  SCIP_SET* set, /**< global SCIP settings */
2404  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2405  SCIP_STAT* stat, /**< problem statistics */
2406  const char* str, /**< string to parse */
2407  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2408  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2409  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2410  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2411  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2412  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2413  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2414  char** endptr, /**< pointer to store the final string position if successfully */
2415  SCIP_Bool* success /**< pointer store if the paring process was successful */
2416  )
2417 {
2418  char name[SCIP_MAXSTRLEN];
2419  SCIP_Real lb;
2420  SCIP_Real ub;
2421  SCIP_Real obj;
2422  SCIP_VARTYPE vartype;
2423  SCIP_Real lazylb;
2424  SCIP_Real lazyub;
2425 
2426  assert(var != NULL);
2427  assert(blkmem != NULL);
2428  assert(stat != NULL);
2429  assert(endptr != NULL);
2430  assert(success != NULL);
2431 
2432  /* parse string in cip format for variable information */
2433  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2434 
2435  if( *success )
2436  {
2437  /* create variable */
2438  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2439  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2440 
2441  /* set variable status and data */
2442  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2443  (*var)->data.original.origdom.holelist = NULL;
2444  (*var)->data.original.origdom.lb = lb;
2445  (*var)->data.original.origdom.ub = ub;
2446  (*var)->data.original.transvar = NULL;
2447 
2448  /* set lazy status of variable bounds */
2449  (*var)->lazylb = lazylb;
2450  (*var)->lazyub = lazyub;
2451 
2452  /* capture variable */
2453  SCIPvarCapture(*var);
2454  }
2455 
2456  return SCIP_OKAY;
2457 }
2458 
2459 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2460  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2461  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2462  * variable
2463  */
2465  SCIP_VAR** var, /**< pointer to variable data */
2466  BMS_BLKMEM* blkmem, /**< block memory */
2467  SCIP_SET* set, /**< global SCIP settings */
2468  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2469  SCIP_STAT* stat, /**< problem statistics */
2470  const char* str, /**< string to parse */
2471  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2472  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2473  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2474  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2475  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2476  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2477  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2478  char** endptr, /**< pointer to store the final string position if successfully */
2479  SCIP_Bool* success /**< pointer store if the paring process was successful */
2480  )
2481 {
2482  char name[SCIP_MAXSTRLEN];
2483  SCIP_Real lb;
2484  SCIP_Real ub;
2485  SCIP_Real obj;
2486  SCIP_VARTYPE vartype;
2487  SCIP_Real lazylb;
2488  SCIP_Real lazyub;
2489 
2490  assert(var != NULL);
2491  assert(blkmem != NULL);
2492  assert(endptr != NULL);
2493  assert(success != NULL);
2494 
2495  /* parse string in cip format for variable information */
2496  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2497 
2498  if( *success )
2499  {
2500  /* create variable */
2501  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2502  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2503 
2504  /* create event filter for transformed variable */
2505  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2506 
2507  /* set variable status and data */
2508  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2509 
2510  /* set lazy status of variable bounds */
2511  (*var)->lazylb = lazylb;
2512  (*var)->lazyub = lazyub;
2513 
2514  /* capture variable */
2515  SCIPvarCapture(*var);
2516  }
2517 
2518  return SCIP_OKAY;
2519 }
2520 
2521 /** ensures, that parentvars array of var can store at least num entries */
2522 static
2524  SCIP_VAR* var, /**< problem variable */
2525  BMS_BLKMEM* blkmem, /**< block memory */
2526  SCIP_SET* set, /**< global SCIP settings */
2527  int num /**< minimum number of entries to store */
2528  )
2529 {
2530  assert(var->nparentvars <= var->parentvarssize);
2531 
2532  if( num > var->parentvarssize )
2533  {
2534  int newsize;
2535 
2536  newsize = SCIPsetCalcMemGrowSize(set, num);
2537  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2538  var->parentvarssize = newsize;
2539  }
2540  assert(num <= var->parentvarssize);
2541 
2542  return SCIP_OKAY;
2543 }
2544 
2545 /** adds variable to parent list of a variable and captures parent variable */
2546 static
2548  SCIP_VAR* var, /**< variable to add parent to */
2549  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2550  SCIP_SET* set, /**< global SCIP settings */
2551  SCIP_VAR* parentvar /**< parent variable to add */
2552  )
2553 {
2554  assert(var != NULL);
2555  assert(parentvar != NULL);
2556 
2557  /* the direct original counterpart must be stored as first parent */
2558  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2559 
2560  SCIPdebugMessage("adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2561  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2562 
2563  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2564 
2565  var->parentvars[var->nparentvars] = parentvar;
2566  var->nparentvars++;
2567 
2568  SCIPvarCapture(parentvar);
2569 
2570  return SCIP_OKAY;
2571 }
2572 
2573 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2574 static
2576  SCIP_VAR** var, /**< pointer to variable */
2577  BMS_BLKMEM* blkmem, /**< block memory */
2578  SCIP_SET* set, /**< global SCIP settings */
2579  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2580  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2581  )
2582 {
2583  SCIP_VAR* parentvar;
2584  int i;
2585 
2586  SCIPdebugMessage("free parents of <%s>\n", (*var)->name);
2587 
2588  /* release the parent variables and remove the link from the parent variable to the child */
2589  for( i = 0; i < (*var)->nparentvars; ++i )
2590  {
2591  assert((*var)->parentvars != NULL);
2592  parentvar = (*var)->parentvars[i];
2593  assert(parentvar != NULL);
2594 
2595  switch( SCIPvarGetStatus(parentvar) )
2596  {
2598  assert(parentvar->data.original.transvar == *var);
2599  assert(&parentvar->data.original.transvar != var);
2600  parentvar->data.original.transvar = NULL;
2601  break;
2602 
2604  assert(parentvar->data.aggregate.var == *var);
2605  assert(&parentvar->data.aggregate.var != var);
2606  parentvar->data.aggregate.var = NULL;
2607  break;
2608 
2609 #if 0
2610  /* The following code is unclear: should the current variable be removed from its parents? */
2612  assert(parentvar->data.multaggr.vars != NULL);
2613  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2614  {}
2615  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2616  if( v < parentvar->data.multaggr.nvars-1 )
2617  {
2618  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2619  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2620  }
2621  parentvar->data.multaggr.nvars--;
2622  break;
2623 #endif
2624 
2626  assert(parentvar->negatedvar == *var);
2627  assert((*var)->negatedvar == parentvar);
2628  parentvar->negatedvar = NULL;
2629  (*var)->negatedvar = NULL;
2630  break;
2631 
2632  default:
2633  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2634  return SCIP_INVALIDDATA;
2635  } /*lint !e788*/
2636 
2637  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2638  }
2639 
2640  /* free parentvars array */
2641  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2642 
2643  return SCIP_OKAY;
2644 }
2645 
2646 /** frees a variable */
2647 static
2649  SCIP_VAR** var, /**< pointer to variable */
2650  BMS_BLKMEM* blkmem, /**< block memory */
2651  SCIP_SET* set, /**< global SCIP settings */
2652  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2653  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2654  )
2655 {
2656  assert(var != NULL);
2657  assert(*var != NULL);
2658  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2659  assert((*var)->nuses == 0);
2660  assert((*var)->probindex == -1);
2661 
2662  SCIPdebugMessage("free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2663 
2664  switch( SCIPvarGetStatus(*var) )
2665  {
2667  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2668  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2669  assert((*var)->data.original.origdom.holelist == NULL);
2670  break;
2671  case SCIP_VARSTATUS_LOOSE:
2672  break;
2673  case SCIP_VARSTATUS_COLUMN:
2674  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2675  break;
2676  case SCIP_VARSTATUS_FIXED:
2678  break;
2680  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2681  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2682  break;
2684  break;
2685  default:
2686  SCIPerrorMessage("unknown variable status\n");
2687  return SCIP_INVALIDDATA;
2688  }
2689 
2690  /* release all parent variables and free the parentvars array */
2691  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2692 
2693  /* free user data */
2695  {
2696  if( (*var)->vardelorig != NULL )
2697  {
2698  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2699  }
2700  }
2701  else
2702  {
2703  if( (*var)->vardeltrans != NULL )
2704  {
2705  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2706  }
2707  }
2708 
2709  /* free event filter */
2710  if( (*var)->eventfilter != NULL )
2711  {
2712  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2713  }
2714  assert((*var)->eventfilter == NULL);
2715 
2716  /* free hole lists */
2717  holelistFree(&(*var)->glbdom.holelist, blkmem);
2718  holelistFree(&(*var)->locdom.holelist, blkmem);
2719  assert((*var)->glbdom.holelist == NULL);
2720  assert((*var)->locdom.holelist == NULL);
2721 
2722  /* free variable bounds data structures */
2723  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2724  SCIPvboundsFree(&(*var)->vubs, blkmem);
2725 
2726  /* free implications data structures */
2727  SCIPimplicsFree(&(*var)->implics, blkmem);
2728 
2729  /* free clique list data structures */
2730  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2731 
2732  /* free bound change information arrays */
2733  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2734  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2735 
2736  /* free branching and inference history entries */
2737  SCIPhistoryFree(&(*var)->history, blkmem);
2738  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2739  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2740 
2741  /* free variable data structure */
2742  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2743  BMSfreeBlockMemory(blkmem, var);
2744 
2745  return SCIP_OKAY;
2746 }
2747 
2748 /** increases usage counter of variable */
2749 void SCIPvarCapture(
2750  SCIP_VAR* var /**< variable */
2751  )
2752 {
2753  assert(var != NULL);
2754  assert(var->nuses >= 0);
2755 
2756  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2757  var->nuses++;
2758 }
2759 
2760 /** decreases usage counter of variable, and frees memory if necessary */
2762  SCIP_VAR** var, /**< pointer to variable */
2763  BMS_BLKMEM* blkmem, /**< block memory */
2764  SCIP_SET* set, /**< global SCIP settings */
2765  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2766  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2767  )
2768 {
2769  assert(var != NULL);
2770  assert(*var != NULL);
2771  assert((*var)->nuses >= 1);
2772  assert(blkmem != NULL);
2773  assert((*var)->scip == set->scip);
2774 
2775  SCIPdebugMessage("release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2776  (*var)->nuses--;
2777  if( (*var)->nuses == 0 )
2778  {
2779  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2780  }
2781 
2782  *var = NULL;
2783 
2784  return SCIP_OKAY;
2785 }
2786 
2787 /** change variable name */
2789  SCIP_VAR* var, /**< problem variable */
2790  BMS_BLKMEM* blkmem, /**< block memory */
2791  const char* name /**< name of variable */
2792  )
2793 {
2794  assert(name != NULL);
2795 
2796  /* remove old variable name */
2797  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2798 
2799  /* set new variable name */
2800  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2801 
2802  return SCIP_OKAY;
2803 }
2804 
2805 /** initializes variable data structure for solving */
2806 void SCIPvarInitSolve(
2807  SCIP_VAR* var /**< problem variable */
2808  )
2809 {
2810  assert(var != NULL);
2811 
2813  var->conflictlbcount = 0;
2814  var->conflictubcount = 0;
2815 }
2816 
2817 /** outputs the given bounds into the file stream */
2818 static
2819 void printBounds(
2820  SCIP_SET* set, /**< global SCIP settings */
2821  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2822  FILE* file, /**< output file (or NULL for standard output) */
2823  SCIP_Real lb, /**< lower bound */
2824  SCIP_Real ub, /**< upper bound */
2825  const char* name /**< bound type name */
2826  )
2827 {
2828  assert(set != NULL);
2829 
2830  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2831  if( SCIPsetIsInfinity(set, lb) )
2832  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2833  else if( SCIPsetIsInfinity(set, -lb) )
2834  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2835  else
2836  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2837  if( SCIPsetIsInfinity(set, ub) )
2838  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2839  else if( SCIPsetIsInfinity(set, -ub) )
2840  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2841  else
2842  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2843 }
2844 
2845 /** prints hole list to file stream */
2846 static
2847 void printHolelist(
2848  SCIP_SET* set, /**< global SCIP settings */
2849  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2850  FILE* file, /**< output file (or NULL for standard output) */
2851  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2852  const char* name /**< hole type name */
2853  )
2854 { /*lint --e{715}*/
2855  SCIP_Real left;
2856  SCIP_Real right;
2857 
2858  if( holelist == NULL )
2859  return;
2860 
2861  left = SCIPholelistGetLeft(holelist);
2862  right = SCIPholelistGetRight(holelist);
2863 
2864  /* display first hole */
2865  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2866  holelist = SCIPholelistGetNext(holelist);
2867 
2868  while(holelist != NULL )
2869  {
2870  left = SCIPholelistGetLeft(holelist);
2871  right = SCIPholelistGetRight(holelist);
2872 
2873  /* display hole */
2874  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2875 
2876  /* get next hole */
2877  holelist = SCIPholelistGetNext(holelist);
2878  }
2879 }
2880 
2881 /** outputs variable information into file stream */
2883  SCIP_VAR* var, /**< problem variable */
2884  SCIP_SET* set, /**< global SCIP settings */
2885  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2886  FILE* file /**< output file (or NULL for standard output) */
2887  )
2888 {
2889  SCIP_HOLELIST* holelist;
2890  SCIP_Real lb;
2891  SCIP_Real ub;
2892  int i;
2893 
2894  assert(var != NULL);
2895  assert(var->scip == set->scip);
2896 
2897  /* type of variable */
2898  switch( SCIPvarGetType(var) )
2899  {
2900  case SCIP_VARTYPE_BINARY:
2901  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2902  break;
2903  case SCIP_VARTYPE_INTEGER:
2904  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2905  break;
2906  case SCIP_VARTYPE_IMPLINT:
2907  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2908  break;
2910  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2911  break;
2912  default:
2913  SCIPerrorMessage("unknown variable type\n");
2914  SCIPABORT();
2915  return SCIP_ERROR; /*lint !e527*/
2916  }
2917 
2918  /* name */
2919  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2920 
2921  /* objective value */
2922  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2923 
2924  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2925  if( !SCIPvarIsTransformed(var) )
2926  {
2927  /* output original bound */
2928  lb = SCIPvarGetLbOriginal(var);
2929  ub = SCIPvarGetUbOriginal(var);
2930  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2931 
2932  /* output lazy bound */
2933  lb = SCIPvarGetLbLazy(var);
2934  ub = SCIPvarGetUbLazy(var);
2935 
2936  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2937  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2938  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2939 
2940  holelist = SCIPvarGetHolelistOriginal(var);
2941  printHolelist(set, messagehdlr, file, holelist, "original holes");
2942  }
2943  else
2944  {
2945  /* output global bound */
2946  lb = SCIPvarGetLbGlobal(var);
2947  ub = SCIPvarGetUbGlobal(var);
2948  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2949 
2950  /* output local bound */
2951  lb = SCIPvarGetLbLocal(var);
2952  ub = SCIPvarGetUbLocal(var);
2953  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2954 
2955  /* output lazy bound */
2956  lb = SCIPvarGetLbLazy(var);
2957  ub = SCIPvarGetUbLazy(var);
2958 
2959  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2960  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2961  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2962 
2963  /* global hole list */
2964  holelist = SCIPvarGetHolelistGlobal(var);
2965  printHolelist(set, messagehdlr, file, holelist, "global holes");
2966 
2967  /* local hole list */
2968  holelist = SCIPvarGetHolelistLocal(var);
2969  printHolelist(set, messagehdlr, file, holelist, "local holes");
2970  }
2971 
2972  /* fixings and aggregations */
2973  switch( SCIPvarGetStatus(var) )
2974  {
2976  case SCIP_VARSTATUS_LOOSE:
2977  case SCIP_VARSTATUS_COLUMN:
2978  break;
2979 
2980  case SCIP_VARSTATUS_FIXED:
2981  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
2982  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
2983  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
2984  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
2985  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
2986  else
2987  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
2988  break;
2989 
2991  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2992  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
2993  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
2994  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
2995  break;
2996 
2998  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2999  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3000  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3001  for( i = 0; i < var->data.multaggr.nvars; ++i )
3002  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3003  break;
3004 
3006  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3007  break;
3008 
3009  default:
3010  SCIPerrorMessage("unknown variable status\n");
3011  SCIPABORT();
3012  return SCIP_ERROR; /*lint !e527*/
3013  }
3014 
3015  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3016 
3017  return SCIP_OKAY;
3018 }
3019 
3020 /** issues a VARUNLOCKED event on the given variable */
3021 static
3023  SCIP_VAR* var, /**< problem variable to change */
3024  BMS_BLKMEM* blkmem, /**< block memory */
3025  SCIP_SET* set, /**< global SCIP settings */
3026  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3027  )
3028 {
3029  SCIP_EVENT* event;
3030 
3031  assert(var != NULL);
3032  assert(var->nlocksdown <= 1 && var->nlocksup <= 1);
3033  assert(var->scip == set->scip);
3034 
3035  /* issue VARUNLOCKED event on variable */
3036  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3037  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3038 
3039  return SCIP_OKAY;
3040 }
3041 
3042 /** modifies lock numbers for rounding */
3044  SCIP_VAR* var, /**< problem variable */
3045  BMS_BLKMEM* blkmem, /**< block memory */
3046  SCIP_SET* set, /**< global SCIP settings */
3047  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3048  int addnlocksdown, /**< increase in number of rounding down locks */
3049  int addnlocksup /**< increase in number of rounding up locks */
3050  )
3051 {
3052  SCIP_VAR* lockvar;
3053 
3054  assert(var != NULL);
3055  assert(var->nlocksup >= 0);
3056  assert(var->nlocksdown >= 0);
3057  assert(var->scip == set->scip);
3058 
3059  if( addnlocksdown == 0 && addnlocksup == 0 )
3060  return SCIP_OKAY;
3061 
3062  SCIPdebugMessage("add rounding locks %d/%d to variable <%s> (locks=%d/%d)\n",
3063  addnlocksdown, addnlocksup, var->name, var->nlocksdown, var->nlocksup);
3064 
3065  lockvar = var;
3066 
3067  while( TRUE ) /*lint !e716 */
3068  {
3069  assert(lockvar != NULL);
3070 
3071  switch( SCIPvarGetStatus(lockvar) )
3072  {
3074  if( lockvar->data.original.transvar != NULL )
3075  {
3076  lockvar = lockvar->data.original.transvar;
3077  break;
3078  }
3079  else
3080  {
3081  lockvar->nlocksdown += addnlocksdown;
3082  lockvar->nlocksup += addnlocksup;
3083 
3084  assert(lockvar->nlocksdown >= 0);
3085  assert(lockvar->nlocksup >= 0);
3086 
3087  return SCIP_OKAY;
3088  }
3089  case SCIP_VARSTATUS_LOOSE:
3090  case SCIP_VARSTATUS_COLUMN:
3091  case SCIP_VARSTATUS_FIXED:
3092  lockvar->nlocksdown += addnlocksdown;
3093  lockvar->nlocksup += addnlocksup;
3094 
3095  assert(lockvar->nlocksdown >= 0);
3096  assert(lockvar->nlocksup >= 0);
3097 
3098  if( lockvar->nlocksdown <= 1 && lockvar->nlocksup <= 1 )
3099  {
3100  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3101  }
3102 
3103  return SCIP_OKAY;
3105  if( lockvar->data.aggregate.scalar < 0.0 )
3106  {
3107  int tmp = addnlocksup;
3108 
3109  addnlocksup = addnlocksdown;
3110  addnlocksdown = tmp;
3111  }
3112 
3113  lockvar = lockvar->data.aggregate.var;
3114  break;
3116  {
3117  int v;
3118 
3119  assert(!lockvar->donotmultaggr);
3120 
3121  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3122  {
3123  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3124  {
3125  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue,
3126  addnlocksdown, addnlocksup) );
3127  }
3128  else
3129  {
3130  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue,
3131  addnlocksup, addnlocksdown) );
3132  }
3133  }
3134  return SCIP_OKAY;
3135  }
3137  {
3138  int tmp = addnlocksup;
3139 
3140  assert(lockvar->negatedvar != NULL);
3141  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3142  assert(lockvar->negatedvar->negatedvar == lockvar);
3143 
3144  addnlocksup = addnlocksdown;
3145  addnlocksdown = tmp;
3146 
3147  lockvar = lockvar->negatedvar;
3148  break;
3149  }
3150  default:
3151  SCIPerrorMessage("unknown variable status\n");
3152  return SCIP_INVALIDDATA;
3153  }
3154  }
3155 }
3156 
3157 /** gets number of locks for rounding down */
3159  SCIP_VAR* var /**< problem variable */
3160  )
3161 {
3162  int nlocks;
3163  int i;
3164 
3165  assert(var != NULL);
3166  assert(var->nlocksdown >= 0);
3167 
3168  switch( SCIPvarGetStatus(var) )
3169  {
3171  if( var->data.original.transvar != NULL )
3173  else
3174  return var->nlocksdown;
3175 
3176  case SCIP_VARSTATUS_LOOSE:
3177  case SCIP_VARSTATUS_COLUMN:
3178  case SCIP_VARSTATUS_FIXED:
3179  return var->nlocksdown;
3180 
3182  if( var->data.aggregate.scalar > 0.0 )
3183  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3184  else
3185  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3186 
3188  assert(!var->donotmultaggr);
3189  nlocks = 0;
3190  for( i = 0; i < var->data.multaggr.nvars; ++i )
3191  {
3192  if( var->data.multaggr.scalars[i] > 0.0 )
3193  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3194  else
3195  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3196  }
3197  return nlocks;
3198 
3200  assert(var->negatedvar != NULL);
3202  assert(var->negatedvar->negatedvar == var);
3203  return SCIPvarGetNLocksUp(var->negatedvar);
3204 
3205  default:
3206  SCIPerrorMessage("unknown variable status\n");
3207  SCIPABORT();
3208  return INT_MAX; /*lint !e527*/
3209  }
3210 }
3211 
3212 /** gets number of locks for rounding up */
3213 int SCIPvarGetNLocksUp(
3214  SCIP_VAR* var /**< problem variable */
3215  )
3216 {
3217  int nlocks;
3218  int i;
3219 
3220  assert(var != NULL);
3221  assert(var->nlocksup >= 0);
3222 
3223  switch( SCIPvarGetStatus(var) )
3224  {
3226  if( var->data.original.transvar != NULL )
3228  else
3229  return var->nlocksup;
3230 
3231  case SCIP_VARSTATUS_LOOSE:
3232  case SCIP_VARSTATUS_COLUMN:
3233  case SCIP_VARSTATUS_FIXED:
3234  return var->nlocksup;
3235 
3237  if( var->data.aggregate.scalar > 0.0 )
3238  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3239  else
3240  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3241 
3243  assert(!var->donotmultaggr);
3244  nlocks = 0;
3245  for( i = 0; i < var->data.multaggr.nvars; ++i )
3246  {
3247  if( var->data.multaggr.scalars[i] > 0.0 )
3248  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3249  else
3250  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3251  }
3252  return nlocks;
3253 
3255  assert(var->negatedvar != NULL);
3257  assert(var->negatedvar->negatedvar == var);
3258  return SCIPvarGetNLocksDown(var->negatedvar);
3259 
3260  default:
3261  SCIPerrorMessage("unknown variable status\n");
3262  SCIPABORT();
3263  return INT_MAX; /*lint !e527*/
3264  }
3265 }
3266 
3267 /** is it possible, to round variable down and stay feasible? */
3269  SCIP_VAR* var /**< problem variable */
3270  )
3271 {
3272  return (SCIPvarGetNLocksDown(var) == 0);
3273 }
3274 
3275 /** is it possible, to round variable up and stay feasible? */
3277  SCIP_VAR* var /**< problem variable */
3278  )
3279 {
3280  return (SCIPvarGetNLocksUp(var) == 0);
3281 }
3282 
3283 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3284  * a new transformed variable for this variable is created
3285  */
3287  SCIP_VAR* origvar, /**< original problem variable */
3288  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3289  SCIP_SET* set, /**< global SCIP settings */
3290  SCIP_STAT* stat, /**< problem statistics */
3291  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3292  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3293  )
3294 {
3295  char name[SCIP_MAXSTRLEN];
3296 
3297  assert(origvar != NULL);
3298  assert(origvar->scip == set->scip);
3299  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3300  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3301  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3302  assert(origvar->vlbs == NULL);
3303  assert(origvar->vubs == NULL);
3304  assert(transvar != NULL);
3305 
3306  /* check if variable is already transformed */
3307  if( origvar->data.original.transvar != NULL )
3308  {
3309  *transvar = origvar->data.original.transvar;
3310  SCIPvarCapture(*transvar);
3311  }
3312  else
3313  {
3314  /* create transformed variable */
3315  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3316  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3317  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3318  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3319  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3320 
3321  /* copy the branch factor and priority */
3322  (*transvar)->branchfactor = origvar->branchfactor;
3323  (*transvar)->branchpriority = origvar->branchpriority;
3324  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3325 
3326  /* duplicate hole lists */
3327  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3328  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3329 
3330  /* link original and transformed variable */
3331  origvar->data.original.transvar = *transvar;
3332  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3333 
3334  /* copy rounding locks */
3335  (*transvar)->nlocksdown = origvar->nlocksdown;
3336  (*transvar)->nlocksup = origvar->nlocksup;
3337  assert((*transvar)->nlocksdown >= 0);
3338  assert((*transvar)->nlocksup >= 0);
3339 
3340  /* copy doNotMultiaggr status */
3341  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3342 
3343  /* copy lazy bounds */
3344  (*transvar)->lazylb = origvar->lazylb;
3345  (*transvar)->lazyub = origvar->lazyub;
3346 
3347  /* transform user data */
3348  if( origvar->vartrans != NULL )
3349  {
3350  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3351  }
3352  else
3353  (*transvar)->vardata = origvar->vardata;
3354  }
3355 
3356  SCIPdebugMessage("transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3357 
3358  return SCIP_OKAY;
3359 }
3360 
3361 /** gets corresponding transformed variable of an original or negated original variable */
3363  SCIP_VAR* origvar, /**< original problem variable */
3364  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3365  SCIP_SET* set, /**< global SCIP settings */
3366  SCIP_STAT* stat, /**< problem statistics */
3367  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3368  )
3369 {
3370  assert(origvar != NULL);
3372  assert(origvar->scip == set->scip);
3373 
3374  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3375  {
3376  assert(origvar->negatedvar != NULL);
3378 
3379  if( origvar->negatedvar->data.original.transvar == NULL )
3380  *transvar = NULL;
3381  else
3382  {
3383  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3384  }
3385  }
3386  else
3387  *transvar = origvar->data.original.transvar;
3388 
3389  return SCIP_OKAY;
3390 }
3391 
3392 /** converts loose transformed variable into column variable, creates LP column */
3394  SCIP_VAR* var, /**< problem variable */
3395  BMS_BLKMEM* blkmem, /**< block memory */
3396  SCIP_SET* set, /**< global SCIP settings */
3397  SCIP_STAT* stat, /**< problem statistics */
3398  SCIP_PROB* prob, /**< problem data */
3399  SCIP_LP* lp /**< current LP data */
3400  )
3401 {
3402  assert(var != NULL);
3403  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3404  assert(var->scip == set->scip);
3405 
3406  SCIPdebugMessage("creating column for variable <%s>\n", var->name);
3407 
3408  /* switch variable status */
3409  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3410 
3411  /* create column of variable */
3412  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3413 
3414  if( var->probindex != -1 )
3415  {
3416  /* inform problem about the variable's status change */
3417  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, var) );
3418 
3419  /* inform LP, that problem variable is now a column variable and no longer loose */
3420  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3421  }
3422 
3423  return SCIP_OKAY;
3424 }
3425 
3426 /** converts column transformed variable back into loose variable, frees LP column */
3428  SCIP_VAR* var, /**< problem variable */
3429  BMS_BLKMEM* blkmem, /**< block memory */
3430  SCIP_SET* set, /**< global SCIP settings */
3431  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3432  SCIP_PROB* prob, /**< problem data */
3433  SCIP_LP* lp /**< current LP data */
3434  )
3435 {
3436  assert(var != NULL);
3437  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3438  assert(var->scip == set->scip);
3439  assert(var->data.col != NULL);
3440  assert(var->data.col->lppos == -1);
3441  assert(var->data.col->lpipos == -1);
3442 
3443  SCIPdebugMessage("deleting column for variable <%s>\n", var->name);
3444 
3445  /* free column of variable */
3446  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3447 
3448  /* switch variable status */
3449  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3450 
3451  if( var->probindex != -1 )
3452  {
3453  /* inform problem about the variable's status change */
3454  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, var) );
3455 
3456  /* inform LP, that problem variable is now a loose variable and no longer a column */
3457  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3458  }
3459 
3460  return SCIP_OKAY;
3461 }
3462 
3463 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3464  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3465  * are not informed about a fixing of an active variable they are pointing to
3466  */
3467 static
3469  SCIP_VAR* var, /**< problem variable to change */
3470  BMS_BLKMEM* blkmem, /**< block memory */
3471  SCIP_SET* set, /**< global SCIP settings */
3472  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3473  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3474  * multi-aggregation(2)
3475  */
3476  )
3477 {
3478  SCIP_EVENT* event;
3479  SCIP_VARSTATUS varstatus;
3480  int i;
3481 
3482  assert(var != NULL);
3483  assert(var->scip == set->scip);
3484  assert(0 <= fixeventtype && fixeventtype <= 2);
3485 
3486  /* issue VARFIXED event on variable */
3487  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3488  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3489 
3490 #ifndef NDEBUG
3491  for( i = var->nparentvars -1; i >= 0; --i )
3492  {
3494  }
3495 #endif
3496 
3497  switch( fixeventtype )
3498  {
3499  case 0:
3500  /* process all parents of a fixed variable */
3501  for( i = var->nparentvars - 1; i >= 0; --i )
3502  {
3503  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3504 
3505  assert(varstatus != SCIP_VARSTATUS_FIXED);
3506 
3507  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3508  * one
3509  */
3510  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3511  {
3512  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3513  }
3514  }
3515  break;
3516  case 1:
3517  /* process all parents of a aggregated variable */
3518  for( i = var->nparentvars - 1; i >= 0; --i )
3519  {
3520  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3521 
3522  assert(varstatus != SCIP_VARSTATUS_FIXED);
3523 
3524  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3525  * issued(, except the original one)
3526  *
3527  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3528  * yet issued
3529  */
3530  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3531  continue;
3532 
3533  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3534  {
3535  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3536  }
3537  }
3538  break;
3539  case 2:
3540  /* process all parents of a aggregated variable */
3541  for( i = var->nparentvars - 1; i >= 0; --i )
3542  {
3543  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3544 
3545  assert(varstatus != SCIP_VARSTATUS_FIXED);
3546 
3547  /* issue event on all parent variables except the original one */
3548  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3549  {
3550  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3551  }
3552  }
3553  break;
3554  default:
3555  SCIPerrorMessage("unknown variable fixation event origin\n");
3556  return SCIP_INVALIDDATA;
3557  }
3558 
3559  return SCIP_OKAY;
3560 }
3561 
3562 /** converts variable into fixed variable */
3564  SCIP_VAR* var, /**< problem variable */
3565  BMS_BLKMEM* blkmem, /**< block memory */
3566  SCIP_SET* set, /**< global SCIP settings */
3567  SCIP_STAT* stat, /**< problem statistics */
3568  SCIP_PROB* transprob, /**< tranformed problem data */
3569  SCIP_PROB* origprob, /**< original problem data */
3570  SCIP_PRIMAL* primal, /**< primal data */
3571  SCIP_TREE* tree, /**< branch and bound tree */
3572  SCIP_LP* lp, /**< current LP data */
3573  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3574  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3575  SCIP_Real fixedval, /**< value to fix variable at */
3576  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3577  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3578  )
3579 {
3580  SCIP_Real obj;
3581  SCIP_Real childfixedval;
3582 
3583  assert(var != NULL);
3584  assert(var->scip == set->scip);
3585  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3586  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3587  assert(infeasible != NULL);
3588  assert(fixed != NULL);
3589 
3590  SCIPdebugMessage("fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3591 
3592  *infeasible = FALSE;
3593  *fixed = FALSE;
3594 
3596  {
3597  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3598  SCIPdebugMessage(" -> variable already fixed to %g (fixedval=%g): infeasible=%u\n",
3599  var->locdom.lb, fixedval, *infeasible);
3600  return SCIP_OKAY;
3601  }
3602  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3603  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3604  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3605  {
3606  SCIPdebugMessage(" -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3607  *infeasible = TRUE;
3608  return SCIP_OKAY;
3609  }
3610 
3611  switch( SCIPvarGetStatus(var) )
3612  {
3614  if( var->data.original.transvar == NULL )
3615  {
3616  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3617  return SCIP_INVALIDDATA;
3618  }
3619  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
3620  fixedval, infeasible, fixed) );
3621  break;
3622 
3623  case SCIP_VARSTATUS_LOOSE:
3624  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3625 
3626  /* set the fixed variable's objective value to 0.0 */
3627  obj = var->obj;
3628  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3629 
3630  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3631  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3632  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3633  * objective of this variable is set to zero
3634  */
3635  SCIPlpDecNLoosevars(lp);
3636 
3637  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3638  holelistFree(&var->glbdom.holelist, blkmem);
3639  holelistFree(&var->locdom.holelist, blkmem);
3640  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, fixedval) );
3641  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, fixedval) );
3642 
3643  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3644  var->glbdom.lb = fixedval;
3645  var->glbdom.ub = fixedval;
3646  var->locdom.lb = fixedval;
3647  var->locdom.ub = fixedval;
3648 
3649  /* delete implications and variable bounds information */
3650  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, FALSE, TRUE) );
3651  assert(var->vlbs == NULL);
3652  assert(var->vubs == NULL);
3653  assert(var->implics == NULL);
3654 
3655  /* remove the variable from all cliques */
3656  if( SCIPvarIsBinary(var) )
3657  {
3659  SCIPcliquelistFree(&var->cliquelist, blkmem);
3660  }
3661  assert(var->cliquelist == NULL);
3662 
3663  /* clear the history of the variable */
3664  SCIPhistoryReset(var->history);
3666 
3667  /* convert variable into fixed variable */
3668  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3669 
3670  /* inform problem about the variable's status change */
3671  if( var->probindex != -1 )
3672  {
3673  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, var) );
3674  }
3675 
3676  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3677  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue, obj) );
3678 
3679  /* issue VARFIXED event */
3680  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3681 
3682  *fixed = TRUE;
3683  break;
3684 
3685  case SCIP_VARSTATUS_COLUMN:
3686  SCIPerrorMessage("cannot fix a column variable\n");
3687  return SCIP_INVALIDDATA;
3688 
3689  case SCIP_VARSTATUS_FIXED:
3690  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3691  SCIPABORT(); /* case is already handled in earlier if condition */
3692  return SCIP_INVALIDDATA; /*lint !e527*/
3693 
3695  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3696  assert(SCIPsetIsZero(set, var->obj));
3697  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3698  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3699  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3700  else
3701  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3702  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
3703  childfixedval, infeasible, fixed) );
3704  break;
3705 
3707  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3708  SCIPABORT();
3709  return SCIP_INVALIDDATA; /*lint !e527*/
3710 
3712  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3713  assert(SCIPsetIsZero(set, var->obj));
3714  assert(var->negatedvar != NULL);
3716  assert(var->negatedvar->negatedvar == var);
3717  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
3718  var->data.negate.constant - fixedval, infeasible, fixed) );
3719  break;
3720 
3721  default:
3722  SCIPerrorMessage("unknown variable status\n");
3723  return SCIP_INVALIDDATA;
3724  }
3725 
3726  return SCIP_OKAY;
3727 }
3728 
3729 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3730  *
3731  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3732  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3733  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3734  *
3735  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3736  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3737  */
3739  SCIP_SET* set, /**< global SCIP settings */
3740  SCIP_VAR** vars, /**< variable array to get active variables */
3741  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3742  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3743  int varssize, /**< available slots in vars and scalars array */
3744  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3745  int* requiredsize, /**< pointer to store the required array size for the active variables */
3746  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3747  )
3748 {
3749  SCIP_VAR** activevars;
3750  SCIP_Real* activescalars;
3751  int nactivevars;
3752  SCIP_Real activeconstant;
3753  SCIP_Bool activeconstantinf;
3754  int activevarssize;
3755 
3756  SCIP_VAR* var;
3757  SCIP_Real scalar;
3758  int v;
3759 
3760  SCIP_VAR** tmpvars;
3761  SCIP_VAR** multvars;
3762  SCIP_Real* tmpscalars;
3763  SCIP_Real* multscalars;
3764  int tmpvarssize;
3765  int ntmpvars;
3766  int nmultvars;
3767 
3768  SCIP_VAR* multvar;
3769  SCIP_Real multscalar;
3770  SCIP_Real multconstant;
3771  int pos;
3772 
3773  int noldtmpvars;
3774 
3775  SCIP_VAR** tmpvars2;
3776  SCIP_Real* tmpscalars2;
3777  int tmpvarssize2;
3778  int ntmpvars2;
3779 
3780  assert(set != NULL);
3781  assert(nvars != NULL);
3782  assert(vars != NULL || *nvars == 0);
3783  assert(scalars != NULL || *nvars == 0);
3784  assert(constant != NULL);
3785  assert(requiredsize != NULL);
3786  assert(*nvars <= varssize);
3787 
3788  *requiredsize = 0;
3789 
3790  if( *nvars == 0 )
3791  return SCIP_OKAY;
3792 
3793  assert(vars != NULL);
3794 
3795  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3796  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3797  {
3798  *requiredsize = 1;
3799 
3800  return SCIP_OKAY;
3801  }
3802 
3803  nactivevars = 0;
3804  activeconstant = 0.0;
3805  activeconstantinf = FALSE;
3806  activevarssize = (*nvars) * 2;
3807  ntmpvars = *nvars;
3808  tmpvarssize = *nvars;
3809 
3810  tmpvarssize2 = 1;
3811  ntmpvars2 = 0;
3812 
3813  /* allocate temporary memory */
3814  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3815  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3816  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3817  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3818  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3819  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3820 
3821  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3822  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3823  */
3824  for( v = ntmpvars - 1; v >= 0; --v )
3825  {
3826  var = tmpvars[v];
3827  scalar = tmpscalars[v];
3828 
3829  assert(var != NULL);
3830  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3831  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3832  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3833  */
3834  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3835  assert(var != NULL);
3836 
3837  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3838  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3839 
3840  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3841 
3842  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3843  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3846 
3847  tmpvars[v] = var;
3848  tmpscalars[v] = scalar;
3849  }
3850  noldtmpvars = ntmpvars;
3851 
3852  /* sort all variables to combine equal variables easily */
3853  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3854  for( v = ntmpvars - 1; v > 0; --v )
3855  {
3856  /* combine same variables */
3857  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
3858  {
3859  tmpscalars[v - 1] += tmpscalars[v];
3860  --ntmpvars;
3861  tmpvars[v] = tmpvars[ntmpvars];
3862  tmpscalars[v] = tmpscalars[ntmpvars];
3863  }
3864  }
3865  /* sort all variables again to combine equal variables later on */
3866  if( noldtmpvars > ntmpvars )
3867  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3868 
3869  /* collect for each variable the representation in active variables */
3870  while( ntmpvars >= 1 )
3871  {
3872  --ntmpvars;
3873  ntmpvars2 = 0;
3874  var = tmpvars[ntmpvars];
3875  scalar = tmpscalars[ntmpvars];
3876 
3877  assert(var != NULL);
3878 
3879  if( scalar == 0.0 )
3880  continue;
3881 
3882  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3883  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3886 
3887  switch( SCIPvarGetStatus(var) )
3888  {
3889  case SCIP_VARSTATUS_LOOSE:
3890  case SCIP_VARSTATUS_COLUMN:
3891  /* x = a*y + c */
3892  if( nactivevars >= activevarssize )
3893  {
3894  activevarssize *= 2;
3895  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3896  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3897  assert(nactivevars < activevarssize);
3898  }
3899  activevars[nactivevars] = var;
3900  activescalars[nactivevars] = scalar;
3901  nactivevars++;
3902  break;
3903 
3905  /* x = a_1*y_1 + ... + a_n*y_n + c */
3906  nmultvars = var->data.multaggr.nvars;
3907  multvars = var->data.multaggr.vars;
3908  multscalars = var->data.multaggr.scalars;
3909 
3910  if( nmultvars + ntmpvars > tmpvarssize )
3911  {
3912  while( nmultvars + ntmpvars > tmpvarssize )
3913  tmpvarssize *= 2;
3914  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3915  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3916  assert(nmultvars + ntmpvars <= tmpvarssize);
3917  }
3918 
3919  if( nmultvars > tmpvarssize2 )
3920  {
3921  while( nmultvars > tmpvarssize2 )
3922  tmpvarssize2 *= 2;
3923  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3924  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3925  assert(nmultvars <= tmpvarssize2);
3926  }
3927 
3928  --nmultvars;
3929 
3930  for( ; nmultvars >= 0; --nmultvars )
3931  {
3932  multvar = multvars[nmultvars];
3933  multscalar = multscalars[nmultvars];
3934  multconstant = 0;
3935 
3936  assert(multvar != NULL);
3937  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
3938  assert(multvar != NULL);
3939 
3940  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3941  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3944 
3945  if( !activeconstantinf )
3946  {
3947  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
3948 
3949  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
3950  {
3951  assert(scalar != 0.0);
3952  if( scalar * multconstant > 0.0 )
3953  {
3954  activeconstant = SCIPsetInfinity(set);
3955  activeconstantinf = TRUE;
3956  }
3957  else
3958  {
3959  activeconstant = -SCIPsetInfinity(set);
3960  activeconstantinf = TRUE;
3961  }
3962  }
3963  else
3964  activeconstant += scalar * multconstant;
3965  }
3966 #ifndef NDEBUG
3967  else
3968  {
3969  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
3970  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3971  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
3972  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3973  }
3974 #endif
3975 
3976  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
3977  {
3978  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
3979  tmpscalars[pos] += scalar * multscalar;
3980  }
3981  else
3982  {
3983  tmpvars2[ntmpvars2] = multvar;
3984  tmpscalars2[ntmpvars2] = scalar * multscalar;
3985  ++(ntmpvars2);
3986  assert(ntmpvars2 <= tmpvarssize2);
3987  }
3988  }
3989 
3990  /* sort all variables to combine equal variables easily */
3991  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
3992  for( v = ntmpvars2 - 1; v > 0; --v )
3993  {
3994  /* combine same variables */
3995  if( SCIPvarCompare(tmpvars2[v], tmpvars2[v - 1]) == 0 )
3996  {
3997  tmpscalars2[v - 1] += tmpscalars2[v];
3998  --ntmpvars2;
3999  tmpvars2[v] = tmpvars2[ntmpvars2];
4000  tmpscalars2[v] = tmpscalars2[ntmpvars2];
4001  }
4002  }
4003 
4004  for( v = 0; v < ntmpvars2; ++v )
4005  {
4006  tmpvars[ntmpvars] = tmpvars2[v];
4007  tmpscalars[ntmpvars] = tmpscalars2[v];
4008  ++(ntmpvars);
4009  assert(ntmpvars <= tmpvarssize);
4010  }
4011  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
4012 
4013  if( !activeconstantinf )
4014  {
4015  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4016 
4017  multconstant = SCIPvarGetMultaggrConstant(var);
4018 
4019  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4020  {
4021  assert(scalar != 0.0);
4022  if( scalar * multconstant > 0.0 )
4023  {
4024  activeconstant = SCIPsetInfinity(set);
4025  activeconstantinf = TRUE;
4026  }
4027  else
4028  {
4029  activeconstant = -SCIPsetInfinity(set);
4030  activeconstantinf = TRUE;
4031  }
4032  }
4033  else
4034  activeconstant += scalar * multconstant;
4035  }
4036 #ifndef NDEBUG
4037  else
4038  {
4039  multconstant = SCIPvarGetMultaggrConstant(var);
4040  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4041  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4042  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4043  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4044  }
4045 #endif
4046  break;
4047 
4048  case SCIP_VARSTATUS_FIXED:
4052  default:
4053  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4054  * fixed variables and is handled already
4055  */
4056  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4057  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4058  }
4059  }
4060 
4061  if( mergemultiples )
4062  {
4063  /* sort variable and scalar array by variable index */
4064  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4065 
4066  /* eliminate duplicates and count required size */
4067  v = nactivevars - 1;
4068  while( v > 0 )
4069  {
4070  /* combine both variable since they are the same */
4071  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4072  {
4073  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4074  {
4075  activescalars[v - 1] += activescalars[v];
4076  --nactivevars;
4077  activevars[v] = activevars[nactivevars];
4078  activescalars[v] = activescalars[nactivevars];
4079  }
4080  else
4081  {
4082  --nactivevars;
4083  activevars[v] = activevars[nactivevars];
4084  activescalars[v] = activescalars[nactivevars];
4085  --nactivevars;
4086  --v;
4087  activevars[v] = activevars[nactivevars];
4088  activescalars[v] = activescalars[nactivevars];
4089  }
4090  }
4091  --v;
4092  }
4093  }
4094  *requiredsize = nactivevars;
4095 
4096  if( varssize >= *requiredsize )
4097  {
4098  assert(vars != NULL);
4099 
4100  *nvars = *requiredsize;
4101 
4102  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4103  {
4104  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4105  if( activeconstantinf )
4106  (*constant) = activeconstant;
4107  else
4108  (*constant) += activeconstant;
4109  }
4110 #ifndef NDEBUG
4111  else
4112  {
4113  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4114  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4115  }
4116 #endif
4117 
4118  /* copy active variable and scalar array to the given arrays */
4119  for( v = 0; v < *nvars; ++v )
4120  {
4121  vars[v] = activevars[v];
4122  scalars[v] = activescalars[v]; /*lint !e613*/
4123  }
4124  }
4125 
4126  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4127  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4128 
4129  SCIPsetFreeBufferArray(set, &tmpvars2);
4130  SCIPsetFreeBufferArray(set, &tmpscalars2);
4131  SCIPsetFreeBufferArray(set, &tmpvars);
4132  SCIPsetFreeBufferArray(set, &tmpscalars);
4133  SCIPsetFreeBufferArray(set, &activevars);
4134  SCIPsetFreeBufferArray(set, &activescalars);
4135 
4136  return SCIP_OKAY;
4137 }
4138 
4139 
4140 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4142  SCIP_VAR* var, /**< problem variable */
4143  BMS_BLKMEM* blkmem, /**< block memory */
4144  SCIP_SET* set /**< global SCIP settings */
4145  )
4146 {
4147  SCIP_Real multconstant;
4148  int multvarssize;
4149  int nmultvars;
4150  int multrequiredsize;
4151 
4152  assert( var != NULL );
4153  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4154  assert(var->scip == set->scip);
4155 
4156  multconstant = var->data.multaggr.constant;
4157  nmultvars = var->data.multaggr.nvars;
4158  multvarssize = var->data.multaggr.varssize;
4159 
4160  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4161 
4162  if( multrequiredsize > multvarssize )
4163  {
4164  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4165  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4166  multvarssize = multrequiredsize;
4167  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4168  assert( multrequiredsize <= multvarssize );
4169  }
4170  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4171  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4172  * may loose performance hereby, since aggregated variables are easier to handle.
4173  *
4174  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4175  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4176  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4177  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4178  *
4179  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4180  *
4181  * The same issue appears in the SCIPvarGetProbvar...() methods.
4182  */
4183 
4184  var->data.multaggr.constant = multconstant;
4185  var->data.multaggr.nvars = nmultvars;
4186  var->data.multaggr.varssize = multvarssize;
4187 
4188  return SCIP_OKAY;
4189 }
4190 
4191 
4192 /** tightens the bounds of both variables in aggregation x = a*y + c */
4193 static
4195  SCIP_VAR* var, /**< problem variable */
4196  BMS_BLKMEM* blkmem, /**< block memory */
4197  SCIP_SET* set, /**< global SCIP settings */
4198  SCIP_STAT* stat, /**< problem statistics */
4199  SCIP_PROB* transprob, /**< tranformed problem data */
4200  SCIP_PROB* origprob, /**< original problem data */
4201  SCIP_PRIMAL* primal, /**< primal data */
4202  SCIP_TREE* tree, /**< branch and bound tree */
4203  SCIP_LP* lp, /**< current LP data */
4204  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4205  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4206  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4207  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4208  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4209  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4210  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4211  )
4212 {
4213  SCIP_Real varlb;
4214  SCIP_Real varub;
4215  SCIP_Real aggvarlb;
4216  SCIP_Real aggvarub;
4217  SCIP_Bool aggvarbdschanged;
4218 
4219  assert(var != NULL);
4220  assert(var->scip == set->scip);
4221  assert(aggvar != NULL);
4222  assert(!SCIPsetIsZero(set, scalar));
4223  assert(infeasible != NULL);
4224  assert(fixed != NULL);
4225 
4226  *infeasible = FALSE;
4227  *fixed = FALSE;
4228 
4229  SCIPdebugMessage("updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n",
4230  var->name, scalar, aggvar->name, constant);
4231  SCIPdebugMessage(" old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4232  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4233 
4234  /* loop as long additional changes may be found */
4235  do
4236  {
4237  aggvarbdschanged = FALSE;
4238 
4239  /* update the bounds of the aggregated variable x in x = a*y + c */
4240  if( scalar > 0.0 )
4241  {
4242  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4243  varlb = -SCIPsetInfinity(set);
4244  else
4245  varlb = aggvar->glbdom.lb * scalar + constant;
4246  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4247  varub = SCIPsetInfinity(set);
4248  else
4249  varub = aggvar->glbdom.ub * scalar + constant;
4250  }
4251  else
4252  {
4253  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4254  varub = SCIPsetInfinity(set);
4255  else
4256  varub = aggvar->glbdom.lb * scalar + constant;
4257  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4258  varlb = -SCIPsetInfinity(set);
4259  else
4260  varlb = aggvar->glbdom.ub * scalar + constant;
4261  }
4262  varlb = MAX(varlb, var->glbdom.lb);
4263  varub = MIN(varub, var->glbdom.ub);
4264  SCIPvarAdjustLb(var, set, &varlb);
4265  SCIPvarAdjustUb(var, set, &varub);
4266 
4267  /* check the new bounds */
4268  if( SCIPsetIsGT(set, varlb, varub) )
4269  {
4270  /* the aggregation is infeasible */
4271  *infeasible = TRUE;
4272  return SCIP_OKAY;
4273  }
4274  else if( SCIPsetIsEQ(set, varlb, varub) )
4275  {
4276  /* the aggregated variable is fixed -> fix both variables */
4277  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
4278  varlb, infeasible, fixed) );
4279  if( !(*infeasible) )
4280  {
4281  SCIP_Bool aggfixed;
4282 
4283  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
4284  (varlb-constant)/scalar, infeasible, &aggfixed) );
4285  assert(*fixed == aggfixed);
4286  }
4287  return SCIP_OKAY;
4288  }
4289  else
4290  {
4291  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4292  {
4293  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, varlb) );
4294  }
4295  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4296  {
4297  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, varub) );
4298  }
4299 
4300  /* update the hole list of the aggregation variable */
4301  /**@todo update hole list of aggregation variable */
4302  }
4303 
4304  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4305  if( scalar > 0.0 )
4306  {
4307  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4308  aggvarlb = -SCIPsetInfinity(set);
4309  else
4310  aggvarlb = (var->glbdom.lb - constant) / scalar;
4311  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4312  aggvarub = SCIPsetInfinity(set);
4313  else
4314  aggvarub = (var->glbdom.ub - constant) / scalar;
4315  }
4316  else
4317  {
4318  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4319  aggvarub = SCIPsetInfinity(set);
4320  else
4321  aggvarub = (var->glbdom.lb - constant) / scalar;
4322  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4323  aggvarlb = -SCIPsetInfinity(set);
4324  else
4325  aggvarlb = (var->glbdom.ub - constant) / scalar;
4326  }
4327  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4328  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4329  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4330  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4331 
4332  /* check the new bounds */
4333  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4334  {
4335  /* the aggregation is infeasible */
4336  *infeasible = TRUE;
4337  return SCIP_OKAY;
4338  }
4339  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4340  {
4341  /* the aggregation variable is fixed -> fix both variables */
4342  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue, aggvarlb,
4343  infeasible, fixed) );
4344  if( !(*infeasible) )
4345  {
4346  SCIP_Bool varfixed;
4347 
4348  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
4349  aggvarlb * scalar + constant, infeasible, &varfixed) );
4350  assert(*fixed == varfixed);
4351  }
4352  return SCIP_OKAY;
4353  }
4354  else
4355  {
4356  SCIP_Real oldbd;
4357  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4358  {
4359  oldbd = aggvar->glbdom.lb;
4360  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, aggvarlb) );
4361  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4362  }
4363  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4364  {
4365  oldbd = aggvar->glbdom.ub;
4366  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, aggvarub) );
4367  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4368  }
4369 
4370  /* update the hole list of the aggregation variable */
4371  /**@todo update hole list of aggregation variable */
4372  }
4373  }
4374  while( aggvarbdschanged );
4375 
4376  SCIPdebugMessage(" new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4377  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4378 
4379  return SCIP_OKAY;
4380 }
4381 
4382 /** converts loose variable into aggregated variable */
4384  SCIP_VAR* var, /**< loose problem variable */
4385  BMS_BLKMEM* blkmem, /**< block memory */
4386  SCIP_SET* set, /**< global SCIP settings */
4387  SCIP_STAT* stat, /**< problem statistics */
4388  SCIP_PROB* transprob, /**< tranformed problem data */
4389  SCIP_PROB* origprob, /**< original problem data */
4390  SCIP_PRIMAL* primal, /**< primal data */
4391  SCIP_TREE* tree, /**< branch and bound tree */
4392  SCIP_LP* lp, /**< current LP data */
4393  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4394  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4395  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4396  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4397  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4398  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4399  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4400  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4401  )
4402 {
4403  SCIP_VAR** vars;
4404  SCIP_Real* coefs;
4405  SCIP_Real* constants;
4406  SCIP_Real obj;
4407  SCIP_Real branchfactor;
4408  SCIP_Bool fixed;
4409  int branchpriority;
4410  int nlocksdown;
4411  int nlocksup;
4412  int nvbds;
4413  int i;
4414  int j;
4415 
4416  assert(var != NULL);
4417  assert(var->scip == set->scip);
4418  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4419  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4420  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4421  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4422  assert(infeasible != NULL);
4423  assert(aggregated != NULL);
4424 
4425  *infeasible = FALSE;
4426  *aggregated = FALSE;
4427 
4428  /* get active problem variable of aggregation variable */
4429  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4430 
4431  /* aggregation is a fixing, if the scalar is zero */
4432  if( SCIPsetIsZero(set, scalar) )
4433  {
4434  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue, constant,
4435  infeasible, aggregated) );
4436  return SCIP_OKAY;
4437  }
4438 
4439  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4440  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4441  return SCIP_OKAY;
4442 
4443  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4444  * should be changed in the future
4445  */
4446  if( SCIPvarGetHolelistGlobal(var) != NULL )
4447  return SCIP_OKAY;
4448 
4449  assert(aggvar != NULL);
4450  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4451  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4452  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4453 
4454  SCIPdebugMessage("aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4455  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4456 
4457  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4458  if( var == aggvar )
4459  {
4460  if( SCIPsetIsEQ(set, scalar, 1.0) )
4461  *infeasible = !SCIPsetIsZero(set, constant);
4462  else
4463  {
4464  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
4465  constant/(1.0-scalar), infeasible, aggregated) );
4466  }
4467  return SCIP_OKAY;
4468  }
4469 
4470  /* tighten the bounds of aggregated and aggregation variable */
4471  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue,
4472  aggvar, scalar, constant, infeasible, &fixed) );
4473  if( *infeasible || fixed )
4474  {
4475  *aggregated = fixed;
4476  return SCIP_OKAY;
4477  }
4478 
4479  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4480  * aggregated variable
4481  */
4482  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, FALSE, FALSE) );
4483 
4484  /* set the aggregated variable's objective value to 0.0 */
4485  obj = var->obj;
4486  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4487 
4488  /* unlock all rounding locks */
4489  nlocksdown = var->nlocksdown;
4490  nlocksup = var->nlocksup;
4491  var->nlocksdown = 0;
4492  var->nlocksup = 0;
4493 
4494  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4495  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4496  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4497  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4498  {
4499  /* link both variables as negation pair */
4500  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4501  var->data.negate.constant = 1.0;
4502  var->negatedvar = aggvar;
4503  aggvar->negatedvar = var;
4504 
4505  /* copy doNotMultiaggr status */
4506  aggvar->donotmultaggr |= var->donotmultaggr;
4507 
4508  /* mark both variables to be non-deletable */
4510  SCIPvarMarkNotDeletable(aggvar);
4511  }
4512  else
4513  {
4514  /* convert variable into aggregated variable */
4515  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4516  var->data.aggregate.var = aggvar;
4517  var->data.aggregate.scalar = scalar;
4518  var->data.aggregate.constant = constant;
4519 
4520  /* copy doNotMultiaggr status */
4521  aggvar->donotmultaggr |= var->donotmultaggr;
4522 
4523  /* mark both variables to be non-deletable */
4525  SCIPvarMarkNotDeletable(aggvar);
4526  }
4527 
4528  /* make aggregated variable a parent of the aggregation variable */
4529  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4530 
4531  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variable */
4532  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
4533 
4534  /* move the variable bounds to the aggregation variable:
4535  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4536  * - free the variable bounds data structures
4537  */
4538  if( var->vlbs != NULL )
4539  {
4540  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4541  vars = SCIPvboundsGetVars(var->vlbs);
4542  coefs = SCIPvboundsGetCoefs(var->vlbs);
4543  constants = SCIPvboundsGetConstants(var->vlbs);
4544  for( i = 0; i < nvbds && !(*infeasible); ++i )
4545  {
4546  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable, branchcand,
4547  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4548  }
4549  }
4550  if( var->vubs != NULL )
4551  {
4552  nvbds = SCIPvboundsGetNVbds(var->vubs);
4553  vars = SCIPvboundsGetVars(var->vubs);
4554  coefs = SCIPvboundsGetCoefs(var->vubs);
4555  constants = SCIPvboundsGetConstants(var->vubs);
4556  for( i = 0; i < nvbds && !(*infeasible); ++i )
4557  {
4558  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable, branchcand,
4559  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4560  }
4561  }
4562  SCIPvboundsFree(&var->vlbs, blkmem);
4563  SCIPvboundsFree(&var->vubs, blkmem);
4564 
4565  /* move the implications to the aggregation variable:
4566  * - add all implications again to the variable, thus adding it to the aggregation variable
4567  * - free the implications data structures
4568  */
4569  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4570  {
4571  assert(SCIPvarIsBinary(var));
4572  for( i = 0; i < 2; ++i )
4573  {
4574  SCIP_VAR** implvars;
4575  SCIP_BOUNDTYPE* impltypes;
4576  SCIP_Real* implbounds;
4577  int nimpls;
4578 
4579  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4580  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4581  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4582  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4583 
4584  for( j = 0; j < nimpls && !(*infeasible); ++j )
4585  {
4586  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4587  * implication to the aggregated variable?
4588  */
4589  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable, branchcand,
4590  eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible, NULL) );
4591  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4592  }
4593  }
4594  }
4595  SCIPimplicsFree(&var->implics, blkmem);
4596 
4597  /* move the cliques to the aggregation variable:
4598  * - remove the variable from all cliques it is contained in
4599  * - add all cliques again to the variable, thus adding it to the aggregated variable
4600  * - free the cliquelist data structures
4601  */
4602  if( SCIPvarIsBinary(var) )
4603  {
4605  if( var->cliquelist != NULL && SCIPvarIsBinary(aggvar) )
4606  {
4607  for( i = 0; i < 2; ++i )
4608  {
4609  SCIP_CLIQUE** cliques;
4610  int ncliques;
4611 
4612  ncliques = SCIPcliquelistGetNCliques(var->cliquelist, (SCIP_Bool)i);
4613  cliques = SCIPcliquelistGetCliques(var->cliquelist, (SCIP_Bool)i);
4614  for( j = 0; j < ncliques && !(*infeasible); ++j )
4615  {
4616  SCIP_CALL( SCIPvarAddClique(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
4617  (SCIP_Bool)i, cliques[j], infeasible, NULL) );
4618  assert(ncliques == SCIPcliquelistGetNCliques(var->cliquelist, (SCIP_Bool)i));
4619  }
4620  }
4621  }
4622  SCIPcliquelistFree(&var->cliquelist, blkmem);
4623  }
4624  assert(var->cliquelist == NULL);
4625 
4626  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4627  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4628  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4629  SCIPhistoryReset(var->history);
4631 
4632  /* update flags of aggregation variable */
4633  aggvar->removable &= var->removable;
4634 
4635  /* update branching factors and priorities of both variables to be the maximum of both variables */
4636  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4637  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4638  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4639  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4640  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4641  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4642 
4643  /* update branching direction of both variables to agree to a single direction */
4644  if( scalar >= 0.0 )
4645  {
4647  {
4649  }
4650  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4651  {
4653  }
4654  else if( var->branchdirection != aggvar->branchdirection )
4655  {
4657  }
4658  }
4659  else
4660  {
4662  {
4664  }
4665  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4666  {
4668  }
4669  else if( var->branchdirection != aggvar->branchdirection )
4670  {
4672  }
4673  }
4674 
4675  if( var->probindex != -1 )
4676  {
4677  /* inform problem about the variable's status change */
4678  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, var) );
4679  }
4680 
4681  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4682  * variable and the problem's objective offset
4683  */
4684  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue, obj) );
4685 
4686  /* issue VARFIXED event */
4687  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4688 
4689  *aggregated = TRUE;
4690 
4691  return SCIP_OKAY;
4692 }
4693 
4694 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4695  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4696  *
4697  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4698  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4699  */
4700 static
4702  SCIP_SET* set, /**< global SCIP settings */
4703  BMS_BLKMEM* blkmem, /**< block memory */
4704  SCIP_STAT* stat, /**< problem statistics */
4705  SCIP_PROB* transprob, /**< tranformed problem data */
4706  SCIP_PROB* origprob, /**< original problem data */
4707  SCIP_PRIMAL* primal, /**< primal data */
4708  SCIP_TREE* tree, /**< branch and bound tree */
4709  SCIP_LP* lp, /**< current LP data */
4710  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4711  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4712  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4713  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4714  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4715  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4716  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4717  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4718  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4719  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4720  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4721  )
4722 {
4723  SCIP_VAR* aggvar;
4724  char aggvarname[SCIP_MAXSTRLEN];
4725  SCIP_Longint scalarxn = 0;
4726  SCIP_Longint scalarxd = 0;
4727  SCIP_Longint scalaryn = 0;
4728  SCIP_Longint scalaryd = 0;
4729  SCIP_Longint a;
4730  SCIP_Longint b;
4731  SCIP_Longint c;
4732  SCIP_Longint scm;
4733  SCIP_Longint gcd;
4734  SCIP_Longint currentclass;
4735  SCIP_Longint classstep;
4736  SCIP_Longint xsol;
4737  SCIP_Longint ysol;
4738  SCIP_Bool success;
4739  SCIP_VARTYPE vartype;
4740 
4741 #define MAXDNOM 1000000LL
4742 
4743  assert(set != NULL);
4744  assert(blkmem != NULL);
4745  assert(stat != NULL);
4746  assert(transprob != NULL);
4747  assert(origprob != NULL);
4748  assert(tree != NULL);
4749  assert(lp != NULL);
4750  assert(cliquetable != NULL);
4751  assert(branchcand != NULL);
4752  assert(eventqueue != NULL);
4753  assert(varx != NULL);
4754  assert(vary != NULL);
4755  assert(varx != vary);
4756  assert(infeasible != NULL);
4757  assert(aggregated != NULL);
4758  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4759  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4761  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4763  assert(!SCIPsetIsZero(set, scalarx));
4764  assert(!SCIPsetIsZero(set, scalary));
4765 
4766  *infeasible = FALSE;
4767  *aggregated = FALSE;
4768 
4769  /* get rational representation of coefficients */
4770  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4771  if( success )
4772  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4773  if( !success )
4774  return SCIP_OKAY;
4775  assert(scalarxd >= 1);
4776  assert(scalaryd >= 1);
4777 
4778  /* multiply equality with smallest common denominator */
4779  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4780  a = (scm/scalarxd)*scalarxn;
4781  b = (scm/scalaryd)*scalaryn;
4782  rhs *= scm;
4783 
4784  /* divide equality by the greatest common divisor of a and b */
4785  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4786  a /= gcd;
4787  b /= gcd;
4788  rhs /= gcd;
4789  assert(a != 0);
4790  assert(b != 0);
4791 
4792  /* check, if right hand side is integral */
4793  if( !SCIPsetIsFeasIntegral(set, rhs) )
4794  {
4795  *infeasible = TRUE;
4796  return SCIP_OKAY;
4797  }
4798  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4799 
4800  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4801  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4802  {
4803  /* aggregate x = - b/a*y + c/a */
4804  /*lint --e{653}*/
4805  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventqueue,
4806  vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4807  assert(*aggregated);
4808  return SCIP_OKAY;
4809  }
4810  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4811  {
4812  /* aggregate y = - a/b*x + c/b */
4813  /*lint --e{653}*/
4814  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventqueue,
4815  varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4816  assert(*aggregated);
4817  return SCIP_OKAY;
4818  }
4819 
4820  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4821  * common divisor. Let (x',y') be a solution of the equality
4822  * a*x + b*y == c -> a*x == c - b*y
4823  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4824  */
4825 
4826  /* find initial solution (x',y'):
4827  * - find y' such that c - b*y' is a multiple of a
4828  * - start in equivalence class c%a
4829  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
4830  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
4831  * - 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
4832  * - calculate x' with x' = (c - b*y')/a (which must be integral)
4833  *
4834  * Algorithm works for a > 0 only.
4835  */
4836  if( a < 0 )
4837  {
4838  a = -a;
4839  b = -b;
4840  c = -c;
4841  }
4842  assert(0 <= a);
4843 
4844  /* search upwards from ysol = 0 */
4845  ysol = 0;
4846  currentclass = c%a;
4847  if( currentclass < 0 )
4848  currentclass += a;
4849  assert(0 <= currentclass && currentclass < a);
4850 
4851  classstep = (-b)%a;
4852 
4853  if( classstep < 0 )
4854  classstep += a;
4855  assert(0 <= classstep && classstep < a);
4856 
4857  while( currentclass != 0 )
4858  {
4859  assert(0 <= currentclass && currentclass < a);
4860  currentclass += classstep;
4861  if( currentclass >= a )
4862  currentclass -= a;
4863  ysol++;
4864  }
4865  assert(ysol < a);
4866  assert(((c - b*ysol)%a) == 0);
4867 
4868  xsol = (c - b*ysol)/a;
4869 
4870  /* determine variable type for new artificial variable:
4871  *
4872  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
4873  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
4874  * integral type
4875  */
4878 
4879  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
4880  * - create new integer variable z with infinite bounds
4881  * - aggregate variable x = -b*z + x'
4882  * - aggregate variable y = a*z + y'
4883  * - the bounds of z are calculated automatically during aggregation
4884  */
4885  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
4886  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
4887  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
4889  NULL, NULL, NULL, NULL, NULL) );
4890 
4891  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
4892 
4893  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventqueue,
4894  aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
4895  assert(*aggregated || *infeasible);
4896 
4897  if( !(*infeasible) )
4898  {
4899  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventqueue,
4900  aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
4901  assert(*aggregated || *infeasible);
4902  }
4903 
4904  /* release z */
4905  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
4906 
4907  return SCIP_OKAY;
4908 }
4909 
4910 /** performs second step of SCIPaggregateVars():
4911  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
4912  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
4913  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
4914  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
4915  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
4916  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4917  *
4918  * @todo check for fixings, infeasibility, bound changes, or domain holes:
4919  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
4920  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
4921  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
4922  */
4924  SCIP_SET* set, /**< global SCIP settings */
4925  BMS_BLKMEM* blkmem, /**< block memory */
4926  SCIP_STAT* stat, /**< problem statistics */
4927  SCIP_PROB* transprob, /**< tranformed problem data */
4928  SCIP_PROB* origprob, /**< original problem data */
4929  SCIP_PRIMAL* primal, /**< primal data */
4930  SCIP_TREE* tree, /**< branch and bound tree */
4931  SCIP_LP* lp, /**< current LP data */
4932  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4933  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4934  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4935  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4936  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
4937  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
4938  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4939  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4940  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4941  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4942  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4943  )
4944 {
4945  SCIP_Bool easyaggr;
4946 
4947  assert(set != NULL);
4948  assert(blkmem != NULL);
4949  assert(stat != NULL);
4950  assert(transprob != NULL);
4951  assert(origprob != NULL);
4952  assert(tree != NULL);
4953  assert(lp != NULL);
4954  assert(cliquetable != NULL);
4955  assert(branchcand != NULL);
4956  assert(eventqueue != NULL);
4957  assert(varx != NULL);
4958  assert(vary != NULL);
4959  assert(varx != vary);
4960  assert(infeasible != NULL);
4961  assert(aggregated != NULL);
4962  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4963  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4964  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4965  assert(!SCIPsetIsZero(set, scalarx));
4966  assert(!SCIPsetIsZero(set, scalary));
4967 
4968  *infeasible = FALSE;
4969  *aggregated = FALSE;
4970 
4971  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
4972  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) || (SCIPvarGetType(vary) == SCIPvarGetType(varx) &&
4973  SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary)) )
4974  {
4975  SCIP_VAR* var;
4976  SCIP_Real scalar;
4977 
4978  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
4979  var = vary;
4980  vary = varx;
4981  varx = var;
4982  scalar = scalary;
4983  scalary = scalarx;
4984  scalarx = scalar;
4985  }
4986  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
4987 
4988  /* figure out, which variable should be aggregated */
4989  easyaggr = FALSE;
4990 
4991  /* check if it is an easy aggregation that means:
4992  *
4993  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
4994  */
4995  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
4996  {
4998  {
4999  easyaggr = TRUE;
5000  }
5001  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5002  {
5003  easyaggr = TRUE;
5004  }
5005  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5006  {
5007  /* we have an easy aggregation if we flip the variables x and y */
5008  SCIP_VAR* var;
5009  SCIP_Real scalar;
5010 
5011  /* switch the variables, such that varx is the aggregated variable */
5012  var = vary;
5013  vary = varx;
5014  varx = var;
5015  scalar = scalary;
5016  scalary = scalarx;
5017  scalarx = scalar;
5018  easyaggr = TRUE;
5019  }
5020  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5021  {
5022  /* the aggregation is still easy if both variables are continuous */
5023  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5024  easyaggr = TRUE;
5025  }
5026  }
5027 
5028  /* did we find an "easy" aggregation? */
5029  if( easyaggr )
5030  {
5031  SCIP_Real scalar;
5032  SCIP_Real constant;
5033 
5034  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5035 
5036  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5037  scalar = -scalary/scalarx;
5038  constant = rhs/scalarx;
5039 
5040  /* check aggregation for integer feasibility */
5043  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5044  {
5045  *infeasible = TRUE;
5046  return SCIP_OKAY;
5047  }
5048 
5049  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5050  * since then we would loose the corresponding divisibility property
5051  */
5052  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5053 
5054  /* aggregate the variable */
5055  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventqueue,
5056  vary, scalar, constant, infeasible, aggregated) );
5057  assert(*aggregated || *infeasible);
5058  }
5061  {
5062  /* the variables are both integral: we have to try to find an integer aggregation */
5063  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventfilter, eventqueue,
5064  varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5065  }
5066 
5067  return SCIP_OKAY;
5068 }
5069 
5070 /** converts variable into multi-aggregated variable */
5072  SCIP_VAR* var, /**< problem variable */
5073  BMS_BLKMEM* blkmem, /**< block memory */
5074  SCIP_SET* set, /**< global SCIP settings */
5075  SCIP_STAT* stat, /**< problem statistics */
5076  SCIP_PROB* transprob, /**< tranformed problem data */
5077  SCIP_PROB* origprob, /**< original problem data */
5078  SCIP_PRIMAL* primal, /**< primal data */
5079  SCIP_TREE* tree, /**< branch and bound tree */
5080  SCIP_LP* lp, /**< current LP data */
5081  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5082  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5083  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5084  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5085  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5086  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5087  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5088  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5089  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5090  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5091  )
5092 {
5093  SCIP_VAR** tmpvars;
5094  SCIP_Real* tmpscalars;
5095  SCIP_Real obj;
5096  SCIP_Real branchfactor;
5097  int branchpriority;
5098  SCIP_BRANCHDIR branchdirection;
5099  int nlocksdown;
5100  int nlocksup;
5101  int v;
5102  SCIP_Real tmpconstant;
5103  SCIP_Real tmpscalar;
5104  int ntmpvars;
5105  int tmpvarssize;
5106  int tmprequiredsize;
5107 
5108  assert(var != NULL);
5109  assert(var->scip == set->scip);
5110  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5111  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5112  assert(naggvars == 0 || aggvars != NULL);
5113  assert(naggvars == 0 || scalars != NULL);
5114  assert(infeasible != NULL);
5115  assert(aggregated != NULL);
5116 
5117  SCIPdebugMessage("trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5118 
5119  *infeasible = FALSE;
5120  *aggregated = FALSE;
5121 
5122  switch( SCIPvarGetStatus(var) )
5123  {
5125  if( var->data.original.transvar == NULL )
5126  {
5127  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5128  return SCIP_INVALIDDATA;
5129  }
5130  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, lp,
5131  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5132  break;
5133 
5134  case SCIP_VARSTATUS_LOOSE:
5135  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5136 
5137  /* check if we would create a self-reference */
5138  ntmpvars = naggvars;
5139  tmpvarssize = naggvars;
5140  tmpconstant = constant;
5141  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5142  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5143 
5144  /* get all active variables for multi-aggregation */
5145  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5146  if( tmprequiredsize > tmpvarssize )
5147  {
5148  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5149  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5150  tmpvarssize = tmprequiredsize;
5151  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5152  assert( tmprequiredsize <= tmpvarssize );
5153  }
5154 
5155  tmpscalar = 0.0;
5156 
5157  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5158  * possible multi-aggregated variable
5159  */
5160  for( v = ntmpvars - 1; v >= 0; --v )
5161  {
5162  assert(tmpvars[v] != NULL);
5163  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5164 
5165  if( tmpvars[v]->index == var->index )
5166  {
5167  tmpscalar += tmpscalars[v];
5168  tmpvars[v] = tmpvars[ntmpvars - 1];
5169  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5170  --ntmpvars;
5171  }
5172  }
5173 
5174  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5175  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5176  {
5177  if( ntmpvars == 0 )
5178  {
5179  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5180  {
5181  SCIPdebugMessage("Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5182  goto TERMINATE;
5183  }
5184  else /* 0 = c and c != 0 */
5185  {
5186  SCIPdebugMessage("Multi-aggregation was completely resolved and led to infeasibility.\n");
5187  *infeasible = TRUE;
5188  goto TERMINATE;
5189  }
5190  }
5191  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5192  {
5193  assert(tmpscalars[0] != 0.0);
5194  assert(tmpvars[0] != NULL);
5195 
5196  SCIPdebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5197  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue, -constant/tmpscalars[0],
5198  infeasible, aggregated) );
5199  goto TERMINATE;
5200  }
5201  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 */
5202  {
5203  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5204 
5205  SCIPdebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n", SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5206 
5207  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventfilter, eventqueue,
5208  tmpvars[0], tmpvars[1], tmpscalars[0], tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5209 
5210  goto TERMINATE;
5211  }
5212  else
5213  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5214  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5215  */
5216  goto TERMINATE;
5217  }
5218  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5219  else if( !SCIPsetIsZero(set, tmpscalar) )
5220  {
5221  tmpscalar = 1 - tmpscalar;
5222  tmpconstant /= tmpscalar;
5223  for( v = ntmpvars - 1; v >= 0; --v )
5224  tmpscalars[v] /= tmpscalar;
5225  }
5226 
5227  /* check, if we are in one of the simple cases */
5228  if( ntmpvars == 0 )
5229  {
5230  SCIPdebugMessage("Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5231  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, branchcand, eventqueue, tmpconstant,
5232  infeasible, aggregated) );
5233  goto TERMINATE;
5234  }
5235 
5236  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5237  if( ntmpvars == 1 )
5238  {
5239  SCIPdebugMessage("Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n", SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5240 
5241  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, lp, cliquetable, branchcand, eventfilter, eventqueue,
5242  var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant, infeasible, aggregated) );
5243 
5244  goto TERMINATE;
5245  }
5246 
5247  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5248  * empty hole list; this should be changed in the future */
5249  if( SCIPvarGetHolelistGlobal(var) != NULL )
5250  goto TERMINATE;
5251 
5252  /* if the variable is not allowed to be multi-aggregated */
5253  if( SCIPvarDoNotMultaggr(var) )
5254  {
5255  SCIPdebugMessage("variable is not allowed to be multi-aggregated.\n");
5256  goto TERMINATE;
5257  }
5258 
5259  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5260  * variable bound variable of another variable), we have to remove it from the other variables implications or
5261  * variable bounds
5262  */
5263  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, FALSE, TRUE) );
5264  assert(var->vlbs == NULL);
5265  assert(var->vubs == NULL);
5266  assert(var->implics == NULL);
5267 
5268  /* the variable also has to be removed from all cliques */
5269  if( SCIPvarIsBinary(var) )
5270  {
5272  SCIPcliquelistFree(&var->cliquelist, blkmem);
5273  }
5274  assert(var->cliquelist == NULL);
5275 
5276  /* set the aggregated variable's objective value to 0.0 */
5277  obj = var->obj;
5278  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5279 
5280  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5281  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5282  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5283  * objective of this variable is set to zero
5284  */
5285  SCIPlpDecNLoosevars(lp);
5286 
5287  /* unlock all rounding locks */
5288  nlocksdown = var->nlocksdown;
5289  nlocksup = var->nlocksup;
5290  var->nlocksdown = 0;
5291  var->nlocksup = 0;
5292 
5293  /* convert variable into multi-aggregated variable */
5294  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5295  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5296  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5297  var->data.multaggr.constant = tmpconstant;
5298  var->data.multaggr.nvars = ntmpvars;
5299  var->data.multaggr.varssize = ntmpvars;
5300 
5301  /* mark variable to be non-deletable */
5303 
5304  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variables */
5305  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
5306 
5307  /* update flags and branching factors and priorities of aggregation variables;
5308  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5309  */
5310  branchfactor = var->branchfactor;
5311  branchpriority = var->branchpriority;
5312  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5313 
5314  for( v = 0; v < ntmpvars; ++v )
5315  {
5316  assert(tmpvars[v] != NULL);
5317  tmpvars[v]->removable &= var->removable;
5318  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5319  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5320 
5321  /* mark variable to be non-deletable */
5322  SCIPvarMarkNotDeletable(tmpvars[v]);
5323  }
5324  for( v = 0; v < ntmpvars; ++v )
5325  {
5326  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5327  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5328  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5329  {
5330  if( tmpscalars[v] >= 0.0 )
5331  {
5332  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5333  }
5334  else
5335  {
5336  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5337  }
5338  }
5339  }
5340  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5341  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5342 
5343  if( var->probindex != -1 )
5344  {
5345  /* inform problem about the variable's status change */
5346  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, var) );
5347  }
5348 
5349  /* issue VARFIXED event */
5350  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5351 
5352  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5353  * variables and the problem's objective offset
5354  */
5355  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue, obj) );
5356 
5357  *aggregated = TRUE;
5358 
5359  TERMINATE:
5360  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5361  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5362 
5363  break;
5364 
5365  case SCIP_VARSTATUS_COLUMN:
5366  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5367  return SCIP_INVALIDDATA;
5368 
5369  case SCIP_VARSTATUS_FIXED:
5370  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5371  return SCIP_INVALIDDATA;
5372 
5374  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5375  return SCIP_INVALIDDATA;
5376 
5378  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5379  return SCIP_INVALIDDATA;
5380 
5382  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5383  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5384  */
5385  assert(SCIPsetIsZero(set, var->obj));
5386  assert(var->negatedvar != NULL);
5388  assert(var->negatedvar->negatedvar == var);
5389 
5390  /* switch the signs of the aggregation scalars */
5391  for( v = 0; v < naggvars; ++v )
5392  scalars[v] *= -1.0;
5393 
5394  /* perform the multi aggregation on the negation variable */
5395  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, lp,
5396  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5397  var->data.negate.constant - constant, infeasible, aggregated) );
5398 
5399  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5400  for( v = 0; v < naggvars; ++v )
5401  scalars[v] *= -1.0;
5402  break;
5403 
5404  default:
5405  SCIPerrorMessage("unknown variable status\n");
5406  return SCIP_INVALIDDATA;
5407  }
5408 
5409  return SCIP_OKAY;
5410 }
5411 
5412 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5413  * or for original variables the same variable is returned
5414  */
5415 static
5417  SCIP_VAR* var /**< problem variable */
5418  )
5419 {
5420  SCIP_VAR* retvar;
5421 
5422  assert(var != NULL);
5423 
5424  retvar = var;
5425 
5426  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5427 
5428  while( TRUE ) /*lint !e716 */
5429  {
5430  assert(retvar != NULL);
5431 
5432  switch( SCIPvarGetStatus(retvar) )
5433  {
5435  case SCIP_VARSTATUS_LOOSE:
5436  case SCIP_VARSTATUS_COLUMN:
5437  case SCIP_VARSTATUS_FIXED:
5438  return retvar;
5439 
5441  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5442  if ( retvar->data.multaggr.nvars == 1 )
5443  retvar = retvar->data.multaggr.vars[0];
5444  else
5445  return retvar;
5446  break;
5447 
5449  retvar = retvar->data.aggregate.var;
5450  break;
5451 
5453  retvar = retvar->negatedvar;
5454  break;
5455 
5456  default:
5457  SCIPerrorMessage("unknown variable status\n");
5458  SCIPABORT();
5459  return NULL; /*lint !e527*/
5460  }
5461  }
5462 }
5463 
5464 /** returns whether variable is not allowed to be multi-aggregated */
5466  SCIP_VAR* var /**< problem variable */
5467  )
5468 {
5469  SCIP_VAR* retvar;
5470 
5471  assert(var != NULL);
5472 
5473  retvar = varGetActiveVar(var);
5474  assert(retvar != NULL);
5475 
5476  switch( SCIPvarGetStatus(retvar) )
5477  {
5479  case SCIP_VARSTATUS_LOOSE:
5480  case SCIP_VARSTATUS_COLUMN:
5481  case SCIP_VARSTATUS_FIXED:
5482  return retvar->donotmultaggr;
5483 
5485  return FALSE;
5486 
5489  default:
5490  SCIPerrorMessage("wrong variable status\n");
5491  SCIPABORT();
5492  return FALSE; /*lint !e527 */
5493  }
5494 }
5495 
5496 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5497  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5498  * negated variable is created
5499  */
5501  SCIP_VAR* var, /**< problem variable to negate */
5502  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5503  SCIP_SET* set, /**< global SCIP settings */
5504  SCIP_STAT* stat, /**< problem statistics */
5505  SCIP_VAR** negvar /**< pointer to store the negated variable */
5506  )
5507 {
5508  assert(var != NULL);
5509  assert(var->scip == set->scip);
5510  assert(negvar != NULL);
5511 
5512  /* check, if we already created the negated variable */
5513  if( var->negatedvar == NULL )
5514  {
5515  char negvarname[SCIP_MAXSTRLEN];
5516 
5517  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5518 
5519  SCIPdebugMessage("creating negated variable of <%s>\n", var->name);
5520 
5521  /* negation is only possible for bounded variables */
5522  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5523  {
5524  SCIPerrorMessage("cannot negate unbounded variable\n");
5525  return SCIP_INVALIDDATA;
5526  }
5527 
5528  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5529 
5530  /* create negated variable */
5531  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5532  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5533  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5534  if( SCIPvarIsBinary(var) )
5535  (*negvar)->data.negate.constant = 1.0;
5536  else
5537  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5538 
5539  /* create event filter for transformed variable */
5540  if( SCIPvarIsTransformed(var) )
5541  {
5542  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5543  }
5544 
5545  /* set the bounds corresponding to the negation variable */
5546  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5547  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5548  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5549  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5550  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5551 
5552  /* link the variables together */
5553  var->negatedvar = *negvar;
5554  (*negvar)->negatedvar = var;
5555 
5556  /* mark both variables to be non-deletable */
5558  SCIPvarMarkNotDeletable(*negvar);
5559 
5560  /* copy the branch factor and priority, and use the negative preferred branching direction */
5561  (*negvar)->branchfactor = var->branchfactor;
5562  (*negvar)->branchpriority = var->branchpriority;
5563  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5564 
5565  /* copy doNotMultiaggr status */
5566  (*negvar)->donotmultaggr = var->donotmultaggr;
5567 
5568  /* copy lazy bounds (they have to be flipped) */
5569  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5570  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5571 
5572  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5573  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5574  assert((*negvar)->nuses == 1);
5575  }
5576  assert(var->negatedvar != NULL);
5577 
5578  /* return the negated variable */
5579  *negvar = var->negatedvar;
5580 
5581  /* exactly one variable of the negation pair has to be marked as negated variable */
5583 
5584  return SCIP_OKAY;
5585 }
5586 
5587 /** informs variable that its position in problem's vars array changed */
5588 static
5589 void varSetProbindex(
5590  SCIP_VAR* var, /**< problem variable */
5591  int probindex /**< new problem index of variable (-1 for removal) */
5592  )
5593 {
5594  assert(var != NULL);
5595  assert(probindex >= 0 || var->vlbs == NULL);
5596  assert(probindex >= 0 || var->vubs == NULL);
5597  assert(probindex >= 0 || var->implics == NULL);
5598 
5599  var->probindex = probindex;
5601  {
5602  assert(var->data.col != NULL);
5603  var->data.col->var_probindex = probindex;
5604  }
5605 }
5606 
5607 /** informs variable that its position in problem's vars array changed */
5608 void SCIPvarSetProbindex(
5609  SCIP_VAR* var, /**< problem variable */
5610  int probindex /**< new problem index of variable */
5611  )
5612 {
5613  assert(var != NULL);
5614  assert(probindex >= 0);
5615 
5616  varSetProbindex(var, probindex);
5617 }
5618 
5619 /** gives the variable a new name
5620  *
5621  * @note the old pointer is overwritten, which might result in a memory leakage
5622  */
5624  SCIP_VAR* var, /**< problem variable */
5625  const char* name /**< new name of variable */
5626  )
5627 {
5628  assert(var != NULL);
5629  assert(name != NULL);
5630 
5631  var->name = (char*)name;
5632 }
5633 
5634 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5635  * implication graph;
5636  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5637  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5638  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5639  * than removing the variables one by one, each time updating all lists of the other variables.
5640  */
5642  SCIP_VAR* var, /**< problem variable */
5643  BMS_BLKMEM* blkmem, /**< block memory buffer */
5644  SCIP_SET* set, /**< global SCIP settings */
5645  SCIP_Bool final /**< is this the final removal of all problem variables? */
5646  )
5647 {
5648  assert(SCIPvarGetProbindex(var) >= 0);
5649  assert(var->scip == set->scip);
5650 
5651  /* if the variable is active in the transformed problem, remove it from the implication graph */
5652  if( SCIPvarIsTransformed(var)
5654  {
5655  if( final )
5656  {
5657  /* just destroy the data structures */
5658  SCIPvboundsFree(&var->vlbs, blkmem);
5659  SCIPvboundsFree(&var->vubs, blkmem);
5660  SCIPimplicsFree(&var->implics, blkmem);
5661  }
5662  else
5663  {
5664  /* unlink the variable from all other variables' lists and free the data structures */
5665  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, FALSE, TRUE) );
5666  }
5667  }
5668 
5669  /* mark the variable to be no longer a member of the problem */
5670  varSetProbindex(var, -1);
5671 
5672  return SCIP_OKAY;
5673 }
5674 
5675 /** marks the variable to be deleted from the problem */
5676 void SCIPvarMarkDeleted(
5677  SCIP_VAR* var /**< problem variable */
5678  )
5679 {
5680  assert(var != NULL);
5681  assert(var->probindex != -1);
5682 
5683  var->deleted = TRUE;
5684 }
5685 
5686 /** marks the variable to not to be multi-aggregated */
5688  SCIP_VAR* var /**< problem variable */
5689  )
5690 {
5691  SCIP_VAR* retvar;
5692 
5693  assert(var != NULL);
5694 
5695  retvar = varGetActiveVar(var);
5696  assert(retvar != NULL);
5697 
5698  switch( SCIPvarGetStatus(retvar) )
5699  {
5701  case SCIP_VARSTATUS_LOOSE:
5702  case SCIP_VARSTATUS_COLUMN:
5703  case SCIP_VARSTATUS_FIXED:
5704  retvar->donotmultaggr = TRUE;
5705  break;
5706 
5708  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5709  return SCIP_INVALIDDATA;
5710 
5713  default:
5714  SCIPerrorMessage("wrong variable status\n");
5715  return SCIP_INVALIDDATA;
5716  }
5717 
5718  return SCIP_OKAY;
5719 }
5720 
5721 /** changes type of variable; cannot be called, if var belongs to a problem */
5723  SCIP_VAR* var, /**< problem variable to change */
5724  SCIP_VARTYPE vartype /**< new type of variable */
5725  )
5726 {
5727  assert(var != NULL);
5728 
5729  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5730 
5731  if( var->probindex >= 0 )
5732  {
5733  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5734  return SCIP_INVALIDDATA;
5735  }
5736 
5737  var->vartype = vartype; /*lint !e641*/
5738  if( var->negatedvar != NULL )
5739  var->negatedvar->vartype = vartype; /*lint !e641*/
5740 
5741  return SCIP_OKAY;
5742 }
5743 
5744 /** appends OBJCHANGED event to the event queue */
5745 static
5747  SCIP_VAR* var, /**< problem variable to change */
5748  BMS_BLKMEM* blkmem, /**< block memory */
5749  SCIP_SET* set, /**< global SCIP settings */
5750  SCIP_PRIMAL* primal, /**< primal data */
5751  SCIP_LP* lp, /**< current LP data */
5752  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5753  SCIP_Real oldobj, /**< old objective value for variable */
5754  SCIP_Real newobj /**< new objective value for variable */
5755  )
5756 {
5757  SCIP_EVENT* event;
5758 
5759  assert(var != NULL);
5760  assert(var->scip == set->scip);
5761  assert(var->eventfilter != NULL);
5763  assert(SCIPvarIsTransformed(var));
5764  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5765 
5766  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5767  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5768 
5769  return SCIP_OKAY;
5770 }
5771 
5772 /** changes objective value of variable */
5774  SCIP_VAR* var, /**< variable to change */
5775  BMS_BLKMEM* blkmem, /**< block memory */
5776  SCIP_SET* set, /**< global SCIP settings */
5777  SCIP_PROB* prob, /**< problem data */
5778  SCIP_PRIMAL* primal, /**< primal data */
5779  SCIP_LP* lp, /**< current LP data */
5780  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5781  SCIP_Real newobj /**< new objective value for variable */
5782  )
5783 {
5784  SCIP_Real oldobj;
5785 
5786  assert(var != NULL);
5787  assert(set != NULL);
5788  assert(var->scip == set->scip);
5789 
5790  SCIPdebugMessage("changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5791 
5792  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5793  {
5794  switch( SCIPvarGetStatus(var) )
5795  {
5797  if( var->data.original.transvar != NULL )
5798  {
5799  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue, newobj) );
5800  }
5801  else
5802  {
5803  assert(set->stage == SCIP_STAGE_PROBLEM);
5804  var->obj = newobj;
5805  }
5806  break;
5807 
5808  case SCIP_VARSTATUS_LOOSE:
5809  case SCIP_VARSTATUS_COLUMN:
5810  oldobj = var->obj;
5811  var->obj = newobj;
5812 
5813  /* update the number of variables with non-zero objective coefficient;
5814  * we only want to do the update, if the variable is added to the problem;
5815  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5816  */
5817  if( SCIPvarIsActive(var) )
5818  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
5819 
5820  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5821  break;
5822 
5823  case SCIP_VARSTATUS_FIXED:
5827  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
5828  return SCIP_INVALIDDATA;
5829 
5830  default:
5831  SCIPerrorMessage("unknown variable status\n");
5832  return SCIP_INVALIDDATA;
5833  }
5834  }
5835 
5836  return SCIP_OKAY;
5837 }
5838 
5839 /** adds value to objective value of variable */
5841  SCIP_VAR* var, /**< variable to change */
5842  BMS_BLKMEM* blkmem, /**< block memory */
5843  SCIP_SET* set, /**< global SCIP settings */
5844  SCIP_STAT* stat, /**< problem statistics */
5845  SCIP_PROB* transprob, /**< tranformed problem data */
5846  SCIP_PROB* origprob, /**< original problem data */
5847  SCIP_PRIMAL* primal, /**< primal data */
5848  SCIP_TREE* tree, /**< branch and bound tree */
5849  SCIP_LP* lp, /**< current LP data */
5850  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5851  SCIP_Real addobj /**< additional objective value for variable */
5852  )
5853 {
5854  assert(var != NULL);
5855  assert(set != NULL);
5856  assert(var->scip == set->scip);
5857  assert(set->stage < SCIP_STAGE_INITSOLVE);
5858 
5859  SCIPdebugMessage("adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
5860 
5861  if( !SCIPsetIsZero(set, addobj) )
5862  {
5863  SCIP_Real oldobj;
5864  int i;
5865 
5866  switch( SCIPvarGetStatus(var) )
5867  {
5869  if( var->data.original.transvar != NULL )
5870  {
5871  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue, addobj) );
5872  }
5873  else
5874  {
5875  assert(set->stage == SCIP_STAGE_PROBLEM);
5876  var->obj += addobj;
5877  }
5878  break;
5879 
5880  case SCIP_VARSTATUS_LOOSE:
5881  case SCIP_VARSTATUS_COLUMN:
5882  oldobj = var->obj;
5883  var->obj += addobj;
5884 
5885  /* update the number of variables with non-zero objective coefficient;
5886  * we only want to do the update, if the variable is added to the problem;
5887  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5888  */
5889  if( SCIPvarIsActive(var) )
5890  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
5891 
5892  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5893  break;
5894 
5895  case SCIP_VARSTATUS_FIXED:
5896  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
5897  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
5898  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
5899  break;
5900 
5902  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
5903  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
5904  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
5905  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue,
5906  var->data.aggregate.scalar * addobj) );
5907  break;
5908 
5910  assert(!var->donotmultaggr);
5911  /* 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 */
5912  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
5913  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
5914  for( i = 0; i < var->data.multaggr.nvars; ++i )
5915  {
5916  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree, lp,
5917  eventqueue, var->data.multaggr.scalars[i] * addobj) );
5918  }
5919  break;
5920 
5922  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
5923  assert(var->negatedvar != NULL);
5925  assert(var->negatedvar->negatedvar == var);
5926  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
5927  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, lp) );
5928  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, lp, eventqueue, -addobj) );
5929  break;
5930 
5931  default:
5932  SCIPerrorMessage("unknown variable status\n");
5933  return SCIP_INVALIDDATA;
5934  }
5935  }
5936 
5937  return SCIP_OKAY;
5938 }
5939 
5940 /** changes objective value of variable in current dive */
5942  SCIP_VAR* var, /**< problem variable to change */
5943  SCIP_SET* set, /**< global SCIP settings */
5944  SCIP_LP* lp, /**< current LP data */
5945  SCIP_Real newobj /**< new objective value for variable */
5946  )
5947 {
5948  assert(var != NULL);
5949  assert(set != NULL);
5950  assert(var->scip == set->scip);
5951  assert(lp != NULL);
5952 
5953  SCIPdebugMessage("changing objective of <%s> to %g in current dive\n", var->name, newobj);
5954 
5955  if( SCIPsetIsZero(set, newobj) )
5956  newobj = 0.0;
5957 
5958  /* change objective value of attached variables */
5959  switch( SCIPvarGetStatus(var) )
5960  {
5962  assert(var->data.original.transvar != NULL);
5963  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
5964  break;
5965 
5966  case SCIP_VARSTATUS_COLUMN:
5967  assert(var->data.col != NULL);
5968  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
5969  break;
5970 
5971  case SCIP_VARSTATUS_LOOSE:
5972  case SCIP_VARSTATUS_FIXED:
5973  /* nothing to do here: only the constant shift in objective function would change */
5974  break;
5975 
5976  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
5977  assert(var->data.aggregate.var != NULL);
5978  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
5979  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
5980  /* the constant can be ignored, because it would only affect the objective shift */
5981  break;
5982 
5984  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
5985  return SCIP_INVALIDDATA;
5986 
5987  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
5988  assert(var->negatedvar != NULL);
5990  assert(var->negatedvar->negatedvar == var);
5991  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
5992  /* the offset can be ignored, because it would only affect the objective shift */
5993  break;
5994 
5995  default:
5996  SCIPerrorMessage("unknown variable status\n");
5997  return SCIP_INVALIDDATA;
5998  }
5999 
6000  return SCIP_OKAY;
6001 }
6002 
6003 /** adjust lower bound to integral value, if variable is integral */
6004 void SCIPvarAdjustLb(
6005  SCIP_VAR* var, /**< problem variable */
6006  SCIP_SET* set, /**< global SCIP settings */
6007  SCIP_Real* lb /**< pointer to lower bound to adjust */
6008  )
6009 {
6010  assert(var != NULL);
6011  assert(set != NULL);
6012  assert(var->scip == set->scip);
6013  assert(lb != NULL);
6014 
6015  SCIPdebugMessage("adjust lower bound %g of <%s>\n", *lb, var->name);
6016 
6017  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6018 }
6019 
6020 /** adjust upper bound to integral value, if variable is integral */
6021 void SCIPvarAdjustUb(
6022  SCIP_VAR* var, /**< problem variable */
6023  SCIP_SET* set, /**< global SCIP settings */
6024  SCIP_Real* ub /**< pointer to upper bound to adjust */
6025  )
6026 {
6027  assert(var != NULL);
6028  assert(set != NULL);
6029  assert(var->scip == set->scip);
6030  assert(ub != NULL);
6031 
6032  SCIPdebugMessage("adjust upper bound %g of <%s>\n", *ub, var->name);
6033 
6034  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6035 }
6036 
6037 /** adjust lower or upper bound to integral value, if variable is integral */
6038 void SCIPvarAdjustBd(
6039  SCIP_VAR* var, /**< problem variable */
6040  SCIP_SET* set, /**< global SCIP settings */
6041  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6042  SCIP_Real* bd /**< pointer to bound to adjust */
6043  )
6044 {
6045  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6046 
6047  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6048  SCIPvarAdjustLb(var, set, bd);
6049  else
6050  SCIPvarAdjustUb(var, set, bd);
6051 }
6052 
6053 /** changes lower bound of original variable in original problem */
6055  SCIP_VAR* var, /**< problem variable to change */
6056  SCIP_SET* set, /**< global SCIP settings */
6057  SCIP_Real newbound /**< new bound for variable */
6058  )
6059 {
6060  int i;
6061 
6062  assert(var != NULL);
6063  assert(!SCIPvarIsTransformed(var));
6065  assert(set != NULL);
6066  assert(var->scip == set->scip);
6067  assert(set->stage == SCIP_STAGE_PROBLEM);
6068 
6069  /* check that the bound is feasible */
6070  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6071  /* adjust bound to integral value if variable is of integral type */
6072  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6073 
6074  if( SCIPsetIsZero(set, newbound) )
6075  newbound = 0.0;
6076 
6077  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6079  {
6080  SCIPdebugMessage("changing original lower bound of <%s> from %g to %g\n",
6081  var->name, var->data.original.origdom.lb, newbound);
6082 
6083  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6084  return SCIP_OKAY;
6085 
6086  /* change the bound */
6087  var->data.original.origdom.lb = newbound;
6088  }
6089  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6090  {
6091  assert( var->negatedvar != NULL );
6092  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6093  }
6094 
6095  /* process parent variables */
6096  for( i = 0; i < var->nparentvars; ++i )
6097  {
6098  SCIP_VAR* parentvar;
6099 
6100  parentvar = var->parentvars[i];
6101  assert(parentvar != NULL);
6102  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6103  assert(parentvar->negatedvar == var);
6104  assert(var->negatedvar == parentvar);
6105 
6106  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6107  }
6108 
6109  return SCIP_OKAY;
6110 }
6111 
6112 /** changes upper bound of original variable in original problem */
6114  SCIP_VAR* var, /**< problem variable to change */
6115  SCIP_SET* set, /**< global SCIP settings */
6116  SCIP_Real newbound /**< new bound for variable */
6117  )
6118 {
6119  int i;
6120 
6121  assert(var != NULL);
6122  assert(!SCIPvarIsTransformed(var));
6124  assert(set != NULL);
6125  assert(var->scip == set->scip);
6126  assert(set->stage == SCIP_STAGE_PROBLEM);
6127 
6128  /* check that the bound is feasible */
6129  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6130  /* adjust bound to integral value if variable is of integral type */
6131  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6132 
6133  if( SCIPsetIsZero(set, newbound) )
6134  newbound = 0.0;
6135 
6136  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6138  {
6139  SCIPdebugMessage("changing original upper bound of <%s> from %g to %g\n",
6140  var->name, var->data.original.origdom.ub, newbound);
6141 
6142  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6143  return SCIP_OKAY;
6144 
6145  /* change the bound */
6146  var->data.original.origdom.ub = newbound;
6147  }
6148  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6149  {
6150  assert( var->negatedvar != NULL );
6151  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6152  }
6153 
6154  /* process parent variables */
6155  for( i = 0; i < var->nparentvars; ++i )
6156  {
6157  SCIP_VAR* parentvar;
6158 
6159  parentvar = var->parentvars[i];
6160  assert(parentvar != NULL);
6161  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6162  assert(parentvar->negatedvar == var);
6163  assert(var->negatedvar == parentvar);
6164 
6165  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6166  }
6167 
6168  return SCIP_OKAY;
6169 }
6170 
6171 /** appends GLBCHANGED event to the event queue */
6172 static
6174  SCIP_VAR* var, /**< problem variable to change */
6175  BMS_BLKMEM* blkmem, /**< block memory */
6176  SCIP_SET* set, /**< global SCIP settings */
6177  SCIP_LP* lp, /**< current LP data */
6178  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6179  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6180  SCIP_Real oldbound, /**< old lower bound for variable */
6181  SCIP_Real newbound /**< new lower bound for variable */
6182  )
6183 {
6184  assert(var != NULL);
6185  assert(var->eventfilter != NULL);
6186  assert(SCIPvarIsTransformed(var));
6187  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6188  assert(set != NULL);
6189  assert(var->scip == set->scip);
6190 
6191  /* check, if the variable is being tracked for bound changes
6192  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6193  */
6194  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6197  {
6198  SCIP_EVENT* event;
6199 
6200  SCIPdebugMessage("issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6201 
6202  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6203  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6204  }
6205 
6206  return SCIP_OKAY;
6207 }
6208 
6209 /** appends GUBCHANGED event to the event queue */
6210 static
6212  SCIP_VAR* var, /**< problem variable to change */
6213  BMS_BLKMEM* blkmem, /**< block memory */
6214  SCIP_SET* set, /**< global SCIP settings */
6215  SCIP_LP* lp, /**< current LP data */
6216  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6217  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6218  SCIP_Real oldbound, /**< old lower bound for variable */
6219  SCIP_Real newbound /**< new lower bound for variable */
6220  )
6221 {
6222  assert(var != NULL);
6223  assert(var->eventfilter != NULL);
6224  assert(SCIPvarIsTransformed(var));
6225  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6226  assert(set != NULL);
6227  assert(var->scip == set->scip);
6228 
6229  /* check, if the variable is being tracked for bound changes
6230  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6231  */
6232  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6235  {
6236  SCIP_EVENT* event;
6237 
6238  SCIPdebugMessage("issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6239 
6240  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6241  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6242  }
6243 
6244  return SCIP_OKAY;
6245 }
6246 
6247 /** appends GHOLEADDED event to the event queue */
6248 static
6250  SCIP_VAR* var, /**< problem variable to change */
6251  BMS_BLKMEM* blkmem, /**< block memory */
6252  SCIP_SET* set, /**< global SCIP settings */
6253  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6254  SCIP_Real left, /**< left bound of open interval in new hole */
6255  SCIP_Real right /**< right bound of open interval in new hole */
6256  )
6257 {
6258  assert(var != NULL);
6259  assert(var->eventfilter != NULL);
6260  assert(SCIPvarIsTransformed(var));
6261  assert(set != NULL);
6262  assert(var->scip == set->scip);
6263  assert(SCIPsetIsLT(set, left, right));
6264 
6265  /* check, if the variable is being tracked for bound changes */
6266  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6267  {
6268  SCIP_EVENT* event;
6269 
6270  SCIPdebugMessage("issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6271 
6272  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6273  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6274  }
6275 
6276  return SCIP_OKAY;
6277 }
6278 
6279 /** increases root bound change statistics after a global bound change */
6280 static
6281 void varIncRootboundchgs(
6282  SCIP_VAR* var, /**< problem variable to change */
6283  SCIP_SET* set, /**< global SCIP settings */
6284  SCIP_STAT* stat /**< problem statistics */
6285  )
6286 {
6287  assert(var != NULL);
6288  assert(set != NULL);
6289  assert(var->scip == set->scip);
6290  assert(stat != NULL);
6291 
6292  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6293  {
6294  stat->nrootboundchgs++;
6295  stat->nrootboundchgsrun++;
6296  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6297  {
6298  stat->nrootintfixings++;
6299  stat->nrootintfixingsrun++;
6300  }
6301  }
6302 }
6303 
6304 /* forward declaration, because both methods call each other recursively */
6305 
6306 /* performs the current change in upper bound, changes all parents accordingly */
6307 static
6309  SCIP_VAR* var, /**< problem variable to change */
6310  BMS_BLKMEM* blkmem, /**< block memory */
6311  SCIP_SET* set, /**< global SCIP settings */
6312  SCIP_STAT* stat, /**< problem statistics */
6313  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6314  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6315  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6316  SCIP_Real newbound /**< new bound for variable */
6317  );
6318 
6319 /** performs the current change in lower bound, changes all parents accordingly */
6320 static
6322  SCIP_VAR* var, /**< problem variable to change */
6323  BMS_BLKMEM* blkmem, /**< block memory */
6324  SCIP_SET* set, /**< global SCIP settings */
6325  SCIP_STAT* stat, /**< problem statistics */
6326  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6327  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6328  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6329  SCIP_Real newbound /**< new bound for variable */
6330  )
6331 {
6332  SCIP_VAR* parentvar;
6333  SCIP_Real oldbound;
6334  int i;
6335 
6336  assert(var != NULL);
6337  /* local domains can violate global bounds but not more than feasibility epsilon */
6338  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6339  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6340  assert(blkmem != NULL);
6341  assert(set != NULL);
6342  assert(var->scip == set->scip);
6343  assert(stat != NULL);
6344 
6345  /* adjust bound to integral value if variable is of integral type */
6346  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6347 
6348  /* check that the bound is feasible */
6349  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6350  {
6351  /* due to numerics we only want to be feasible in feasibility tolerance */
6352  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6353  newbound = var->glbdom.ub;
6354  }
6355  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6356 
6357  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6358 
6359  SCIPdebugMessage("process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6360 
6361  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6362  return SCIP_OKAY;
6363 
6364  /* check bound on debugging solution */
6365  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6366 
6367  /* change the bound */
6368  oldbound = var->glbdom.lb;
6369  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6370  var->glbdom.lb = newbound;
6371  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6372  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6373 
6374  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6375  {
6376  /* merges overlapping holes into single holes, moves bounds respectively */
6377  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6378  }
6379 
6380  /* update the root bound changes counters */
6381  varIncRootboundchgs(var, set, stat);
6382 
6383  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6384  * redundant bound changes to be branching decisions
6385  */
6386  for( i = 0; i < var->nlbchginfos; ++i )
6387  {
6388  assert(var->lbchginfos[i].var == var);
6389 
6390  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6391  {
6392  SCIPdebugMessage(" -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6393  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6394  var->lbchginfos[i].oldbound = var->glbdom.lb;
6395  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6396  {
6397  /* this bound change is redundant due to the new global bound */
6398  var->lbchginfos[i].newbound = var->glbdom.lb;
6399  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6400  var->lbchginfos[i].redundant = TRUE;
6401  }
6402  else
6403  break; /* from now on, the remaining local bound changes are not redundant */
6404  }
6405  else
6406  break; /* from now on, the remaining local bound changes are not redundant */
6407  }
6408 
6409  /* remove redundant implications and variable bounds */
6411  {
6412  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, TRUE, TRUE) );
6413  }
6414 
6415  /* issue bound change event */
6416  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6417  if( var->eventfilter != NULL )
6418  {
6419  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6420  }
6421 
6422  /* process parent variables */
6423  for( i = 0; i < var->nparentvars; ++i )
6424  {
6425  parentvar = var->parentvars[i];
6426  assert(parentvar != NULL);
6427 
6428  switch( SCIPvarGetStatus(parentvar) )
6429  {
6431  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6432  break;
6433 
6434  case SCIP_VARSTATUS_COLUMN:
6435  case SCIP_VARSTATUS_LOOSE:
6436  case SCIP_VARSTATUS_FIXED:
6438  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6439  return SCIP_INVALIDDATA;
6440 
6441  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6442  assert(parentvar->data.aggregate.var == var);
6443  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6444  {
6445  SCIP_Real parentnewbound;
6446 
6447  /* a > 0 -> change lower bound of y */
6448  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, -oldbound))
6449  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6450  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6451 
6452  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6453  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6454  else
6455  parentnewbound = newbound;
6456  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, parentnewbound) );
6457  }
6458  else
6459  {
6460  SCIP_Real parentnewbound;
6461 
6462  /* a < 0 -> change upper bound of y */
6463  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6464  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, -oldbound))
6465  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6466  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6467 
6468  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6469  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6470  else
6471  parentnewbound = -newbound;
6472  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, parentnewbound) );
6473  }
6474  break;
6475 
6476  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6477  assert(parentvar->negatedvar != NULL);
6478  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6479  assert(parentvar->negatedvar->negatedvar == parentvar);
6480  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue,
6481  parentvar->data.negate.constant - newbound) );
6482  break;
6483 
6484  default:
6485  SCIPerrorMessage("unknown variable status\n");
6486  return SCIP_INVALIDDATA;
6487  }
6488  }
6489 
6490  return SCIP_OKAY;
6491 }
6492 
6493 /** performs the current change in upper bound, changes all parents accordingly */
6494 static
6496  SCIP_VAR* var, /**< problem variable to change */
6497  BMS_BLKMEM* blkmem, /**< block memory */
6498  SCIP_SET* set, /**< global SCIP settings */
6499  SCIP_STAT* stat, /**< problem statistics */
6500  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6501  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6502  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6503  SCIP_Real newbound /**< new bound for variable */
6504  )
6505 {
6506  SCIP_VAR* parentvar;
6507  SCIP_Real oldbound;
6508  int i;
6509 
6510  assert(var != NULL);
6511  /* local domains can violate global bounds but not more than feasibility epsilon */
6512  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6513  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6514  assert(blkmem != NULL);
6515  assert(set != NULL);
6516  assert(var->scip == set->scip);
6517  assert(stat != NULL);
6518 
6519  /* adjust bound to integral value if variable is of integral type */
6520  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6521 
6522  /* check that the bound is feasible */
6523  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6524  {
6525  /* due to numerics we only want to be feasible in feasibility tolerance */
6526  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6527  newbound = var->glbdom.lb;
6528  }
6529  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6530 
6531  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6532 
6533  SCIPdebugMessage("process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6534 
6535  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6536  return SCIP_OKAY;
6537 
6538  /* check bound on debugging solution */
6539  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6540 
6541  /* change the bound */
6542  oldbound = var->glbdom.ub;
6543  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6544  var->glbdom.ub = newbound;
6545  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6546  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6547 
6548  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6549  {
6550  /* merges overlapping holes into single holes, moves bounds respectively */
6551  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6552  }
6553 
6554  /* update the root bound changes counters */
6555  varIncRootboundchgs(var, set, stat);
6556 
6557  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6558  * redundant bound changes to be branching decisions
6559  */
6560  for( i = 0; i < var->nubchginfos; ++i )
6561  {
6562  assert(var->ubchginfos[i].var == var);
6563  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6564  {
6565  SCIPdebugMessage(" -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6566  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6567  var->ubchginfos[i].oldbound = var->glbdom.ub;
6568  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6569  {
6570  /* this bound change is redundant due to the new global bound */
6571  var->ubchginfos[i].newbound = var->glbdom.ub;
6572  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6573  var->ubchginfos[i].redundant = TRUE;
6574  }
6575  else
6576  break; /* from now on, the remaining local bound changes are not redundant */
6577  }
6578  else
6579  break; /* from now on, the remaining local bound changes are not redundant */
6580  }
6581 
6582  /* remove redundant implications and variable bounds */
6584  {
6585  SCIP_CALL( varRemoveImplicsVbs(var, blkmem, set, TRUE, TRUE) );
6586  }
6587 
6588  /* issue bound change event */
6589  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6590  if( var->eventfilter != NULL )
6591  {
6592  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6593  }
6594 
6595  /* process parent variables */
6596  for( i = 0; i < var->nparentvars; ++i )
6597  {
6598  parentvar = var->parentvars[i];
6599  assert(parentvar != NULL);
6600 
6601  switch( SCIPvarGetStatus(parentvar) )
6602  {
6604  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6605  break;
6606 
6607  case SCIP_VARSTATUS_COLUMN:
6608  case SCIP_VARSTATUS_LOOSE:
6609  case SCIP_VARSTATUS_FIXED:
6611  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6612  return SCIP_INVALIDDATA;
6613 
6614  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6615  assert(parentvar->data.aggregate.var == var);
6616  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6617  {
6618  SCIP_Real parentnewbound;
6619 
6620  /* a > 0 -> change upper bound of y */
6621  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, oldbound))
6622  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6623  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6624  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6625  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6626  else
6627  parentnewbound = newbound;
6628  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, parentnewbound) );
6629  }
6630  else
6631  {
6632  SCIP_Real parentnewbound;
6633 
6634  /* a < 0 -> change lower bound of y */
6635  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6636  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, oldbound))
6637  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6638  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6639  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6640  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6641  else
6642  parentnewbound = -newbound;
6643  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, parentnewbound) );
6644  }
6645  break;
6646 
6647  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6648  assert(parentvar->negatedvar != NULL);
6649  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6650  assert(parentvar->negatedvar->negatedvar == parentvar);
6651  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue,
6652  parentvar->data.negate.constant - newbound) );
6653  break;
6654 
6655  default:
6656  SCIPerrorMessage("unknown variable status\n");
6657  return SCIP_INVALIDDATA;
6658  }
6659  }
6660 
6661  return SCIP_OKAY;
6662 }
6663 
6664 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6665  * updates local lower bound if the global bound is tighter
6666  */
6668  SCIP_VAR* var, /**< problem variable to change */
6669  BMS_BLKMEM* blkmem, /**< block memory */
6670  SCIP_SET* set, /**< global SCIP settings */
6671  SCIP_STAT* stat, /**< problem statistics */
6672  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6673  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6674  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6675  SCIP_Real newbound /**< new bound for variable */
6676  )
6677 {
6678  assert(var != NULL);
6679  assert(blkmem != NULL);
6680  assert(set != NULL);
6681  assert(var->scip == set->scip);
6682 
6683  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6684  * of the domain within feastol
6685  */
6686  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6687 
6688  /* adjust bound to integral value if variable is of integral type */
6689  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6690 
6691  /* check that the adjusted bound is feasible
6692  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6693  * here because we reset bounds to their original value!
6694  */
6695  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6696 
6697  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6698  {
6699  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6700  newbound = MIN(newbound, var->glbdom.ub);
6701  }
6702  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6703 
6704  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6705  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6706  */
6707  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound));
6708 
6709  SCIPdebugMessage("changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6710 
6711  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6712  return SCIP_OKAY;
6713 
6714  /* change bounds of attached variables */
6715  switch( SCIPvarGetStatus(var) )
6716  {
6718  if( var->data.original.transvar != NULL )
6719  {
6720  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6721  newbound) );
6722  }
6723  else
6724  {
6725  assert(set->stage == SCIP_STAGE_PROBLEM);
6726  if( newbound > SCIPvarGetLbLocal(var) )
6727  {
6728  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6729  }
6730  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6731  }
6732  break;
6733 
6734  case SCIP_VARSTATUS_COLUMN:
6735  case SCIP_VARSTATUS_LOOSE:
6736  if( newbound > SCIPvarGetLbLocal(var) )
6737  {
6738  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6739  }
6740  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6741  break;
6742 
6743  case SCIP_VARSTATUS_FIXED:
6744  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6745  return SCIP_INVALIDDATA;
6746 
6747  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6748  assert(var->data.aggregate.var != NULL);
6749  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6750  {
6751  SCIP_Real childnewbound;
6752 
6753  /* a > 0 -> change lower bound of y */
6754  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6755  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6757  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6758  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6759  else
6760  childnewbound = newbound;
6761  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
6762  childnewbound) );
6763  }
6764  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6765  {
6766  SCIP_Real childnewbound;
6767 
6768  /* a < 0 -> change upper bound of y */
6769  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6770  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6772  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6773  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6774  else
6775  childnewbound = -newbound;
6776  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
6777  childnewbound) );
6778  }
6779  else
6780  {
6781  SCIPerrorMessage("scalar is zero in aggregation\n");
6782  return SCIP_INVALIDDATA;
6783  }
6784  break;
6785 
6787  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6788  return SCIP_INVALIDDATA;
6789 
6790  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6791  assert(var->negatedvar != NULL);
6793  assert(var->negatedvar->negatedvar == var);
6794  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
6795  var->data.negate.constant - newbound) );
6796  break;
6797 
6798  default:
6799  SCIPerrorMessage("unknown variable status\n");
6800  return SCIP_INVALIDDATA;
6801  }
6802 
6803  return SCIP_OKAY;
6804 }
6805 
6806 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
6807  * updates local upper bound if the global bound is tighter
6808  */
6810  SCIP_VAR* var, /**< problem variable to change */
6811  BMS_BLKMEM* blkmem, /**< block memory */
6812  SCIP_SET* set, /**< global SCIP settings */
6813  SCIP_STAT* stat, /**< problem statistics */
6814  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6815  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6816  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6817  SCIP_Real newbound /**< new bound for variable */
6818  )
6819 {
6820  assert(var != NULL);
6821  assert(blkmem != NULL);
6822  assert(set != NULL);
6823  assert(var->scip == set->scip);
6824 
6825  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6826  * of the domain within feastol
6827  */
6828  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6829 
6830  /* adjust bound to integral value if variable is of integral type */
6831  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6832 
6833  /* check that the adjusted bound is feasible
6834  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6835  * here because we reset bounds to their original value!
6836  */
6837  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6838 
6839  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6840  {
6841  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
6842  newbound = MAX(newbound, var->glbdom.lb);
6843  }
6844  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6845 
6846  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6847  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6848  */
6849  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound));
6850 
6851  SCIPdebugMessage("changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
6852 
6853  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
6854  return SCIP_OKAY;
6855 
6856  /* change bounds of attached variables */
6857  switch( SCIPvarGetStatus(var) )
6858  {
6860  if( var->data.original.transvar != NULL )
6861  {
6862  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6863  newbound) );
6864  }
6865  else
6866  {
6867  assert(set->stage == SCIP_STAGE_PROBLEM);
6868  if( newbound < SCIPvarGetUbLocal(var) )
6869  {
6870  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6871  }
6872  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6873  }
6874  break;
6875 
6876  case SCIP_VARSTATUS_COLUMN:
6877  case SCIP_VARSTATUS_LOOSE:
6878  if( newbound < SCIPvarGetUbLocal(var) )
6879  {
6880  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6881  }
6882  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6883  break;
6884 
6885  case SCIP_VARSTATUS_FIXED:
6886  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6887  return SCIP_INVALIDDATA;
6888 
6889  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6890  assert(var->data.aggregate.var != NULL);
6891  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6892  {
6893  SCIP_Real childnewbound;
6894 
6895  /* a > 0 -> change lower bound of y */
6896  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6897  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6899  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6900  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6901  else
6902  childnewbound = newbound;
6903  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
6904  childnewbound) );
6905  }
6906  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6907  {
6908  SCIP_Real childnewbound;
6909 
6910  /* a < 0 -> change upper bound of y */
6911  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6912  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6914  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6915  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6916  else
6917  childnewbound = -newbound;
6918  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
6919  childnewbound) );
6920  }
6921  else
6922  {
6923  SCIPerrorMessage("scalar is zero in aggregation\n");
6924  return SCIP_INVALIDDATA;
6925  }
6926  break;
6927 
6929  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6930  return SCIP_INVALIDDATA;
6931 
6932  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6933  assert(var->negatedvar != NULL);
6935  assert(var->negatedvar->negatedvar == var);
6936  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
6937  var->data.negate.constant - newbound) );
6938  break;
6939 
6940  default:
6941  SCIPerrorMessage("unknown variable status\n");
6942  return SCIP_INVALIDDATA;
6943  }
6944 
6945  return SCIP_OKAY;
6946 }
6947 
6948 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
6950  SCIP_VAR* var, /**< problem variable */
6951  SCIP_SET* set, /**< global SCIP settings */
6952  SCIP_Real lazylb /**< the lazy lower bound to be set */
6953  )
6954 {
6955  assert(var != NULL);
6956  assert(var->probindex != -1);
6957  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
6958  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
6959  assert(set != NULL);
6960  assert(var->scip == set->scip);
6961 
6962  /* variable should not be in the LP */
6964  return SCIP_INVALIDCALL;
6965 
6966  var->lazylb = lazylb;
6967 
6968  return SCIP_OKAY;
6969 }
6970 
6971 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
6973  SCIP_VAR* var, /**< problem variable */
6974  SCIP_SET* set, /**< global SCIP settings */
6975  SCIP_Real lazyub /**< the lazy lower bound to be set */
6976  )
6977 {
6978  assert(var != NULL);
6979  assert(var->probindex != -1);
6980  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
6981  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
6982  assert(set != NULL);
6983  assert(var->scip == set->scip);
6984 
6985  /* variable should not be in the LP */
6987  return SCIP_INVALIDCALL;
6988 
6989  var->lazyub = lazyub;
6990 
6991  return SCIP_OKAY;
6992 }
6993 
6994 
6995 /** changes global bound of variable; if possible, adjusts bound to integral value;
6996  * updates local bound if the global bound is tighter
6997  */
6999  SCIP_VAR* var, /**< problem variable to change */
7000  BMS_BLKMEM* blkmem, /**< block memory */
7001  SCIP_SET* set, /**< global SCIP settings */
7002  SCIP_STAT* stat, /**< problem statistics */
7003  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7004  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7005  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7006  SCIP_Real newbound, /**< new bound for variable */
7007  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7008  )
7009 {
7010  /* apply bound change to the LP data */
7011  switch( boundtype )
7012  {
7013  case SCIP_BOUNDTYPE_LOWER:
7014  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7015  case SCIP_BOUNDTYPE_UPPER:
7016  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7017  default:
7018  SCIPerrorMessage("unknown bound type\n");
7019  return SCIP_INVALIDDATA;
7020  }
7021 }
7022 
7023 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7024 static
7026  SCIP_VAR* var, /**< problem variable to change */
7027  BMS_BLKMEM* blkmem, /**< block memory */
7028  SCIP_SET* set, /**< global SCIP settings */
7029  SCIP_LP* lp, /**< current LP data */
7030  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7031  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7032  SCIP_Real oldbound, /**< old lower bound for variable */
7033  SCIP_Real newbound /**< new lower bound for variable */
7034  )
7035 {
7036  assert(var != NULL);
7037  assert(var->eventfilter != NULL);
7038  assert(SCIPvarIsTransformed(var));
7039  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7040  assert(set != NULL);
7041  assert(var->scip == set->scip);
7042 
7043  /* check, if the variable is being tracked for bound changes
7044  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7045  */
7046  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7049  {
7050  SCIP_EVENT* event;
7051 
7052  SCIPdebugMessage("issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7053 
7054  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7055  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7056  }
7057 
7058  return SCIP_OKAY;
7059 }
7060 
7061 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7062 static
7064  SCIP_VAR* var, /**< problem variable to change */
7065  BMS_BLKMEM* blkmem, /**< block memory */
7066  SCIP_SET* set, /**< global SCIP settings */
7067  SCIP_LP* lp, /**< current LP data */
7068  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7069  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7070  SCIP_Real oldbound, /**< old upper bound for variable */
7071  SCIP_Real newbound /**< new upper bound for variable */
7072  )
7073 {
7074  assert(var != NULL);
7075  assert(var->eventfilter != NULL);
7076  assert(SCIPvarIsTransformed(var));
7077  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7078  assert(set != NULL);
7079  assert(var->scip == set->scip);
7080 
7081  /* check, if the variable is being tracked for bound changes
7082  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7083  */
7084  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7087  {
7088  SCIP_EVENT* event;
7089 
7090  SCIPdebugMessage("issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7091 
7092  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7093  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7094  }
7095 
7096  return SCIP_OKAY;
7097 }
7098 
7099 /* forward declaration, because both methods call each other recursively */
7100 
7101 /* performs the current change in upper bound, changes all parents accordingly */
7102 static
7104  SCIP_VAR* var, /**< problem variable to change */
7105  BMS_BLKMEM* blkmem, /**< block memory */
7106  SCIP_SET* set, /**< global SCIP settings */
7107  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7108  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7109  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7110  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7111  SCIP_Real newbound /**< new bound for variable */
7112  );
7113 
7114 /** performs the current change in lower bound, changes all parents accordingly */
7115 static
7117  SCIP_VAR* var, /**< problem variable to change */
7118  BMS_BLKMEM* blkmem, /**< block memory */
7119  SCIP_SET* set, /**< global SCIP settings */
7120  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7121  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7122  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7123  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7124  SCIP_Real newbound /**< new bound for variable */
7125  )
7126 {
7127  SCIP_VAR* parentvar;
7128  SCIP_Real oldbound;
7129  int i;
7130 
7131  assert(var != NULL);
7132  assert(set != NULL);
7133  assert(var->scip == set->scip);
7134  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7135  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7137 
7138  /* check that the bound is feasible */
7139  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7140  /* adjust bound to integral value if variable is of integral type */
7141  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7142 
7143  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7144  {
7145  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7146  newbound = MIN(newbound, var->locdom.ub);
7147  }
7148  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7149 
7150  SCIPdebugMessage("process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7151 
7152  if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7153  return SCIP_OKAY;
7154  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
7155  newbound = var->glbdom.lb;
7156 
7157  /* change the bound */
7158  oldbound = var->locdom.lb;
7159  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7160  var->locdom.lb = newbound;
7161 
7162  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7163  * once update the statistic
7164  */
7165  if( stat != NULL )
7166  stat->domchgcount++;
7167 
7168  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7169  {
7170  /* merges overlapping holes into single holes, moves bounds respectively */
7171  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7172  }
7173 
7174  /* issue bound change event */
7175  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7176  if( var->eventfilter != NULL )
7177  {
7178  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7179  }
7180 
7181  /* process parent variables */
7182  for( i = 0; i < var->nparentvars; ++i )
7183  {
7184  parentvar = var->parentvars[i];
7185  assert(parentvar != NULL);
7186 
7187  switch( SCIPvarGetStatus(parentvar) )
7188  {
7190  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7191  break;
7192 
7193  case SCIP_VARSTATUS_COLUMN:
7194  case SCIP_VARSTATUS_LOOSE:
7195  case SCIP_VARSTATUS_FIXED:
7197  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7198  return SCIP_INVALIDDATA;
7199 
7200  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7201  assert(parentvar->data.aggregate.var == var);
7202  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7203  {
7204  SCIP_Real parentnewbound;
7205 
7206  /* a > 0 -> change lower bound of y */
7207  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, -oldbound))
7208  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7209  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7210 
7211  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7212  {
7213  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7214  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7215  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7216  * as a result, the parent's lower bound is set to it's upper bound, and not above
7217  */
7218  if( parentnewbound > parentvar->glbdom.ub )
7219  {
7220  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7221  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7222  parentnewbound = parentvar->glbdom.ub;
7223  }
7224  }
7225  else
7226  parentnewbound = newbound;
7227  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7228  }
7229  else
7230  {
7231  SCIP_Real parentnewbound;
7232 
7233  /* a < 0 -> change upper bound of y */
7234  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7235  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, -oldbound))
7236  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7237  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7238 
7239  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7240  {
7241  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7242  /* 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
7243  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7244  * as a result, the parent's upper bound is set to it's lower bound, and not below
7245  */
7246  if( parentnewbound < parentvar->glbdom.lb )
7247  {
7248  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7249  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7250  parentnewbound = parentvar->glbdom.lb;
7251  }
7252  }
7253  else
7254  parentnewbound = -newbound;
7255  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7256  }
7257  break;
7258 
7259  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7260  assert(parentvar->negatedvar != NULL);
7261  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7262  assert(parentvar->negatedvar->negatedvar == parentvar);
7263  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7264  parentvar->data.negate.constant - newbound) );
7265  break;
7266 
7267  default:
7268  SCIPerrorMessage("unknown variable status\n");
7269  return SCIP_INVALIDDATA;
7270  }
7271  }
7272 
7273  return SCIP_OKAY;
7274 }
7275 
7276 /** performs the current change in upper bound, changes all parents accordingly */
7277 static
7279  SCIP_VAR* var, /**< problem variable to change */
7280  BMS_BLKMEM* blkmem, /**< block memory */
7281  SCIP_SET* set, /**< global SCIP settings */
7282  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7283  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7284  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7285  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7286  SCIP_Real newbound /**< new bound for variable */
7287  )
7288 {
7289  SCIP_VAR* parentvar;
7290  SCIP_Real oldbound;
7291  int i;
7292 
7293  assert(var != NULL);
7294  assert(set != NULL);
7295  assert(var->scip == set->scip);
7296  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7297  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7299 
7300  /* check that the bound is feasible */
7301  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7302  /* adjust bound to integral value if variable is of integral type */
7303  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7304 
7305  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7306  {
7307  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7308  newbound = MAX(newbound, var->locdom.lb);
7309  }
7310  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7311 
7312  SCIPdebugMessage("process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7313 
7314  if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7315  return SCIP_OKAY;
7316  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
7317  newbound = var->glbdom.ub;
7318 
7319  /* change the bound */
7320  oldbound = var->locdom.ub;
7321  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7322  var->locdom.ub = newbound;
7323 
7324  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7325  * once update the statistic
7326  */
7327  if( stat != NULL )
7328  stat->domchgcount++;
7329 
7330  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7331  {
7332  /* merges overlapping holes into single holes, moves bounds respectively */
7333  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7334  }
7335 
7336  /* issue bound change event */
7337  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7338  if( var->eventfilter != NULL )
7339  {
7340  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7341  }
7342 
7343  /* process parent variables */
7344  for( i = 0; i < var->nparentvars; ++i )
7345  {
7346  parentvar = var->parentvars[i];
7347  assert(parentvar != NULL);
7348 
7349  switch( SCIPvarGetStatus(parentvar) )
7350  {
7352  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7353  break;
7354 
7355  case SCIP_VARSTATUS_COLUMN:
7356  case SCIP_VARSTATUS_LOOSE:
7357  case SCIP_VARSTATUS_FIXED:
7359  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7360  return SCIP_INVALIDDATA;
7361 
7362  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7363  assert(parentvar->data.aggregate.var == var);
7364  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7365  {
7366  SCIP_Real parentnewbound;
7367 
7368  /* a > 0 -> change upper bound of x */
7369  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, oldbound))
7370  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7371  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7372  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7373  {
7374  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7375  /* 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
7376  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7377  * as a result, the parent's upper bound is set to it's lower bound, and not below
7378  */
7379  if( parentnewbound < parentvar->glbdom.lb )
7380  {
7381  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7382  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7383  parentnewbound = parentvar->glbdom.lb;
7384  }
7385  }
7386  else
7387  parentnewbound = newbound;
7388  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7389  }
7390  else
7391  {
7392  SCIP_Real parentnewbound;
7393 
7394  /* a < 0 -> change lower bound of x */
7395  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7396  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, oldbound))
7397  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7398  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7399  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7400  {
7401  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7402  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7403  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7404  * as a result, the parent's lower bound is set to it's upper bound, and not above
7405  */
7406  if( parentnewbound > parentvar->glbdom.ub )
7407  {
7408  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7409  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7410  parentnewbound = parentvar->glbdom.ub;
7411  }
7412  }
7413  else
7414  parentnewbound = -newbound;
7415  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7416  }
7417  break;
7418 
7419  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7420  assert(parentvar->negatedvar != NULL);
7421  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7422  assert(parentvar->negatedvar->negatedvar == parentvar);
7423  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7424  parentvar->data.negate.constant - newbound) );
7425  break;
7426 
7427  default:
7428  SCIPerrorMessage("unknown variable status\n");
7429  return SCIP_INVALIDDATA;
7430  }
7431  }
7432 
7433  return SCIP_OKAY;
7434 }
7435 
7436 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7437  * information in variable
7438  */
7440  SCIP_VAR* var, /**< problem variable to change */
7441  BMS_BLKMEM* blkmem, /**< block memory */
7442  SCIP_SET* set, /**< global SCIP settings */
7443  SCIP_STAT* stat, /**< problem statistics */
7444  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7445  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7446  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7447  SCIP_Real newbound /**< new bound for variable */
7448  )
7449 {
7450  assert(var != NULL);
7451  assert(blkmem != NULL);
7452  assert(set != NULL);
7453  assert(var->scip == set->scip);
7454 
7455  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7456  * of the domain within feastol
7457  */
7458  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7459 
7460  /* adjust bound to integral value if variable is of integral type */
7461  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7462 
7463  /* check that the adjusted bound is feasible */
7464  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7465 
7466  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7467  {
7468  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7469  newbound = MIN(newbound, var->locdom.ub);
7470  }
7471  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7472 
7473  SCIPdebugMessage("changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7474 
7475  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) )
7476  return SCIP_OKAY;
7477 
7478  /* change bounds of attached variables */
7479  switch( SCIPvarGetStatus(var) )
7480  {
7482  if( var->data.original.transvar != NULL )
7483  {
7484  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7485  newbound) );
7486  }
7487  else
7488  {
7489  assert(set->stage == SCIP_STAGE_PROBLEM);
7490  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7491  }
7492  break;
7493 
7494  case SCIP_VARSTATUS_COLUMN:
7495  case SCIP_VARSTATUS_LOOSE:
7496  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7497  break;
7498 
7499  case SCIP_VARSTATUS_FIXED:
7500  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7501  return SCIP_INVALIDDATA;
7502 
7503  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7504  assert(var->data.aggregate.var != NULL);
7505  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7506  {
7507  SCIP_Real childnewbound;
7508 
7509  /* a > 0 -> change lower bound of y */
7510  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7511  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7513  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7514  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7515  else
7516  childnewbound = newbound;
7517  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7518  childnewbound) );
7519  }
7520  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7521  {
7522  SCIP_Real childnewbound;
7523 
7524  /* a < 0 -> change upper bound of y */
7525  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7526  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7528  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7529  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7530  else
7531  childnewbound = -newbound;
7532  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7533  childnewbound) );
7534  }
7535  else
7536  {
7537  SCIPerrorMessage("scalar is zero in aggregation\n");
7538  return SCIP_INVALIDDATA;
7539  }
7540  break;
7541 
7543  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7544  return SCIP_INVALIDDATA;
7545 
7546  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7547  assert(var->negatedvar != NULL);
7549  assert(var->negatedvar->negatedvar == var);
7550  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7551  var->data.negate.constant - newbound) );
7552  break;
7553 
7554  default:
7555  SCIPerrorMessage("unknown variable status\n");
7556  return SCIP_INVALIDDATA;
7557  }
7558 
7559  return SCIP_OKAY;
7560 }
7561 
7562 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7563  * information in variable
7564  */
7566  SCIP_VAR* var, /**< problem variable to change */
7567  BMS_BLKMEM* blkmem, /**< block memory */
7568  SCIP_SET* set, /**< global SCIP settings */
7569  SCIP_STAT* stat, /**< problem statistics */
7570  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7571  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7572  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7573  SCIP_Real newbound /**< new bound for variable */
7574  )
7575 {
7576  assert(var != NULL);
7577  assert(blkmem != NULL);
7578  assert(set != NULL);
7579  assert(var->scip == set->scip);
7580 
7581  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7582  * of the domain within feastol
7583  */
7584  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7585 
7586  /* adjust bound to integral value if variable is of integral type */
7587  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7588 
7589  /* check that the adjusted bound is feasible */
7590  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7591 
7592  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7593  {
7594  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7595  newbound = MAX(newbound, var->locdom.lb);
7596  }
7597  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7598 
7599  SCIPdebugMessage("changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7600 
7601  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) )
7602  return SCIP_OKAY;
7603 
7604  /* change bounds of attached variables */
7605  switch( SCIPvarGetStatus(var) )
7606  {
7608  if( var->data.original.transvar != NULL )
7609  {
7610  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7611  }
7612  else
7613  {
7614  assert(set->stage == SCIP_STAGE_PROBLEM);
7615  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7616  }
7617  break;
7618 
7619  case SCIP_VARSTATUS_COLUMN:
7620  case SCIP_VARSTATUS_LOOSE:
7621  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7622  break;
7623 
7624  case SCIP_VARSTATUS_FIXED:
7625  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7626  return SCIP_INVALIDDATA;
7627 
7628  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7629  assert(var->data.aggregate.var != NULL);
7630  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7631  {
7632  SCIP_Real childnewbound;
7633 
7634  /* a > 0 -> change upper bound of y */
7635  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7636  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7638  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7639  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7640  else
7641  childnewbound = newbound;
7642  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7643  childnewbound) );
7644  }
7645  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7646  {
7647  SCIP_Real childnewbound;
7648 
7649  /* a < 0 -> change lower bound of y */
7650  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7651  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7653  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7654  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7655  else
7656  childnewbound = -newbound;
7657  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7658  childnewbound) );
7659  }
7660  else
7661  {
7662  SCIPerrorMessage("scalar is zero in aggregation\n");
7663  return SCIP_INVALIDDATA;
7664  }
7665  break;
7666 
7668  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7669  return SCIP_INVALIDDATA;
7670 
7671  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7672  assert(var->negatedvar != NULL);
7674  assert(var->negatedvar->negatedvar == var);
7675  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7676  var->data.negate.constant - newbound) );
7677  break;
7678 
7679  default:
7680  SCIPerrorMessage("unknown variable status\n");
7681  return SCIP_INVALIDDATA;
7682  }
7683 
7684  return SCIP_OKAY;
7685 }
7686 
7687 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7688  * information in variable
7689  */
7691  SCIP_VAR* var, /**< problem variable to change */
7692  BMS_BLKMEM* blkmem, /**< block memory */
7693  SCIP_SET* set, /**< global SCIP settings */
7694  SCIP_STAT* stat, /**< problem statistics */
7695  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7696  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7697  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7698  SCIP_Real newbound, /**< new bound for variable */
7699  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7700  )
7701 {
7702  /* apply bound change to the LP data */
7703  switch( boundtype )
7704  {
7705  case SCIP_BOUNDTYPE_LOWER:
7706  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7707  case SCIP_BOUNDTYPE_UPPER:
7708  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7709  default:
7710  SCIPerrorMessage("unknown bound type\n");
7711  return SCIP_INVALIDDATA;
7712  }
7713 }
7714 
7715 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7717  SCIP_VAR* var, /**< problem variable to change */
7718  SCIP_SET* set, /**< global SCIP settings */
7719  SCIP_LP* lp, /**< current LP data */
7720  SCIP_Real newbound /**< new bound for variable */
7721  )
7722 {
7723  assert(var != NULL);
7724  assert(set != NULL);
7725  assert(var->scip == set->scip);
7726  assert(lp != NULL);
7727  assert(SCIPlpDiving(lp));
7728 
7729  /* adjust bound for integral variables */
7730  SCIPvarAdjustLb(var, set, &newbound);
7731 
7732  SCIPdebugMessage("changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7733 
7734  /* change bounds of attached variables */
7735  switch( SCIPvarGetStatus(var) )
7736  {
7738  assert(var->data.original.transvar != NULL);
7739  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7740  break;
7741 
7742  case SCIP_VARSTATUS_COLUMN:
7743  assert(var->data.col != NULL);
7744  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7745  break;
7746 
7747  case SCIP_VARSTATUS_LOOSE:
7748  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7749  return SCIP_INVALIDDATA;
7750 
7751  case SCIP_VARSTATUS_FIXED:
7752  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7753  return SCIP_INVALIDDATA;
7754 
7755  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7756  assert(var->data.aggregate.var != NULL);
7757  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7758  {
7759  SCIP_Real childnewbound;
7760 
7761  /* a > 0 -> change lower bound of y */
7762  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7763  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7764  else
7765  childnewbound = newbound;
7766  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, 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  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7774  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7775  else
7776  childnewbound = -newbound;
7777  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7778  }
7779  else
7780  {
7781  SCIPerrorMessage("scalar is zero in aggregation\n");
7782  return SCIP_INVALIDDATA;
7783  }
7784  break;
7785 
7787  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7788  return SCIP_INVALIDDATA;
7789 
7790  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7791  assert(var->negatedvar != NULL);
7793  assert(var->negatedvar->negatedvar == var);
7794  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7795  break;
7796 
7797  default:
7798  SCIPerrorMessage("unknown variable status\n");
7799  return SCIP_INVALIDDATA;
7800  }
7801 
7802  return SCIP_OKAY;
7803 }
7804 
7805 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
7807  SCIP_VAR* var, /**< problem variable to change */
7808  SCIP_SET* set, /**< global SCIP settings */
7809  SCIP_LP* lp, /**< current LP data */
7810  SCIP_Real newbound /**< new bound for variable */
7811  )
7812 {
7813  assert(var != NULL);
7814  assert(set != NULL);
7815  assert(var->scip == set->scip);
7816  assert(lp != NULL);
7817  assert(SCIPlpDiving(lp));
7818 
7819  /* adjust bound for integral variables */
7820  SCIPvarAdjustUb(var, set, &newbound);
7821 
7822  SCIPdebugMessage("changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
7823 
7824  /* change bounds of attached variables */
7825  switch( SCIPvarGetStatus(var) )
7826  {
7828  assert(var->data.original.transvar != NULL);
7829  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
7830  break;
7831 
7832  case SCIP_VARSTATUS_COLUMN:
7833  assert(var->data.col != NULL);
7834  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
7835  break;
7836 
7837  case SCIP_VARSTATUS_LOOSE:
7838  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7839  return SCIP_INVALIDDATA;
7840 
7841  case SCIP_VARSTATUS_FIXED:
7842  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7843  return SCIP_INVALIDDATA;
7844 
7845  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7846  assert(var->data.aggregate.var != NULL);
7847  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7848  {
7849  SCIP_Real childnewbound;
7850 
7851  /* a > 0 -> change upper bound of y */
7852  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7853  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7854  else
7855  childnewbound = newbound;
7856  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7857  }
7858  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7859  {
7860  SCIP_Real childnewbound;
7861 
7862  /* a < 0 -> change lower bound of y */
7863  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7864  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7865  else
7866  childnewbound = -newbound;
7867  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7868  }
7869  else
7870  {
7871  SCIPerrorMessage("scalar is zero in aggregation\n");
7872  return SCIP_INVALIDDATA;
7873  }
7874  break;
7875 
7877  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7878  return SCIP_INVALIDDATA;
7879 
7880  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7881  assert(var->negatedvar != NULL);
7883  assert(var->negatedvar->negatedvar == var);
7884  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7885  break;
7886 
7887  default:
7888  SCIPerrorMessage("unknown variable status\n");
7889  return SCIP_INVALIDDATA;
7890  }
7891 
7892  return SCIP_OKAY;
7893 }
7894 
7895 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
7896  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
7897  * not updated if bounds of aggregation variables are changing
7898  *
7899  * calling this function for a non-multi-aggregated variable is not allowed
7900  */
7902  SCIP_VAR* var, /**< problem variable */
7903  SCIP_SET* set /**< global SCIP settings */
7904  )
7905 {
7906  int i;
7907  SCIP_Real lb;
7908  SCIP_Real bnd;
7909  SCIP_VAR* aggrvar;
7910  SCIP_Bool posinf;
7911  SCIP_Bool neginf;
7912 
7913  assert(var != NULL);
7914  assert(set != NULL);
7915  assert(var->scip == set->scip);
7917 
7918  posinf = FALSE;
7919  neginf = FALSE;
7920  lb = var->data.multaggr.constant;
7921  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
7922  {
7923  aggrvar = var->data.multaggr.vars[i];
7924  if( var->data.multaggr.scalars[i] > 0.0 )
7925  {
7926  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
7927 
7928  if( SCIPsetIsInfinity(set, bnd) )
7929  posinf = TRUE;
7930  else if( SCIPsetIsInfinity(set, -bnd) )
7931  neginf = TRUE;
7932  else
7933  lb += var->data.multaggr.scalars[i] * bnd;
7934  }
7935  else
7936  {
7937  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
7938 
7939  if( SCIPsetIsInfinity(set, -bnd) )
7940  posinf = TRUE;
7941  else if( SCIPsetIsInfinity(set, bnd) )
7942  neginf = TRUE;
7943  else
7944  lb += var->data.multaggr.scalars[i] * bnd;
7945  }
7946 
7947  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
7948  * variable
7949  */
7950  if( neginf )
7951  return SCIPvarGetLbLocal(var);
7952  }
7953 
7954  /* if positive infinity flag was set to true return infinity */
7955  if( posinf )
7956  return SCIPsetInfinity(set);
7957 
7958  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
7959 }
7960 
7961 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
7962  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
7963  * not updated if bounds of aggregation variables are changing
7964  *
7965  * calling this function for a non-multi-aggregated variable is not allowed
7966  */
7968  SCIP_VAR* var, /**< problem variable */
7969  SCIP_SET* set /**< global SCIP settings */
7970  )
7971 {
7972  int i;
7973  SCIP_Real ub;
7974  SCIP_Real bnd;
7975  SCIP_VAR* aggrvar;
7976  SCIP_Bool posinf;
7977  SCIP_Bool neginf;
7978 
7979  assert(var != NULL);
7980  assert(set != NULL);
7981  assert(var->scip == set->scip);
7983 
7984  posinf = FALSE;
7985  neginf = FALSE;
7986  ub = var->data.multaggr.constant;
7987  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
7988  {
7989  aggrvar = var->data.multaggr.vars[i];
7990  if( var->data.multaggr.scalars[i] > 0.0 )
7991  {
7992  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
7993 
7994  if( SCIPsetIsInfinity(set, bnd) )
7995  posinf = TRUE;
7996  else if( SCIPsetIsInfinity(set, -bnd) )
7997  neginf = TRUE;
7998  else
7999  ub += var->data.multaggr.scalars[i] * bnd;
8000  }
8001  else
8002  {
8003  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8004 
8005  if( SCIPsetIsInfinity(set, -bnd) )
8006  posinf = TRUE;
8007  else if( SCIPsetIsInfinity(set, bnd) )
8008  neginf = TRUE;
8009  else
8010  ub += var->data.multaggr.scalars[i] * bnd;
8011  }
8012 
8013  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8014  * variable
8015  */
8016  if( posinf )
8017  return SCIPvarGetUbLocal(var);
8018  }
8019 
8020  /* if negative infinity flag was set to true return -infinity */
8021  if( neginf )
8022  return -SCIPsetInfinity(set);
8023 
8024  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8025 }
8026 
8027 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8028  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8029  * not updated if bounds of aggregation variables are changing
8030  *
8031  * calling this function for a non-multi-aggregated variable is not allowed
8032  */
8034  SCIP_VAR* var, /**< problem variable */
8035  SCIP_SET* set /**< global SCIP settings */
8036  )
8037 {
8038  int i;
8039  SCIP_Real lb;
8040  SCIP_Real bnd;
8041  SCIP_VAR* aggrvar;
8042  SCIP_Bool posinf;
8043  SCIP_Bool neginf;
8044 
8045  assert(var != NULL);
8046  assert(set != NULL);
8047  assert(var->scip == set->scip);
8049 
8050  posinf = FALSE;
8051  neginf = FALSE;
8052  lb = var->data.multaggr.constant;
8053  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8054  {
8055  aggrvar = var->data.multaggr.vars[i];
8056  if( var->data.multaggr.scalars[i] > 0.0 )
8057  {
8058  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8059 
8060  if( SCIPsetIsInfinity(set, bnd) )
8061  posinf = TRUE;
8062  else if( SCIPsetIsInfinity(set, -bnd) )
8063  neginf = TRUE;
8064  else
8065  lb += var->data.multaggr.scalars[i] * bnd;
8066  }
8067  else
8068  {
8069  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8070 
8071  if( SCIPsetIsInfinity(set, -bnd) )
8072  posinf = TRUE;
8073  else if( SCIPsetIsInfinity(set, bnd) )
8074  neginf = TRUE;
8075  else
8076  lb += var->data.multaggr.scalars[i] * bnd;
8077  }
8078 
8079  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8080  * variable
8081  */
8082  if( neginf )
8083  return SCIPvarGetLbGlobal(var);
8084  }
8085 
8086  /* if positive infinity flag was set to true return infinity */
8087  if( posinf )
8088  return SCIPsetInfinity(set);
8089 
8090  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8091 }
8092 
8093 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8094  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8095  * not updated if bounds of aggregation variables are changing
8096  *
8097  * calling this function for a non-multi-aggregated variable is not allowed
8098  */
8100  SCIP_VAR* var, /**< problem variable */
8101  SCIP_SET* set /**< global SCIP settings */
8102  )
8103 {
8104  int i;
8105  SCIP_Real ub;
8106  SCIP_Real bnd;
8107  SCIP_VAR* aggrvar;
8108  SCIP_Bool posinf;
8109  SCIP_Bool neginf;
8110 
8111  assert(var != NULL);
8112  assert(set != NULL);
8113  assert(var->scip == set->scip);
8115 
8116  posinf = FALSE;
8117  neginf = FALSE;
8118  ub = var->data.multaggr.constant;
8119  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8120  {
8121  aggrvar = var->data.multaggr.vars[i];
8122  if( var->data.multaggr.scalars[i] > 0.0 )
8123  {
8124  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8125 
8126  if( SCIPsetIsInfinity(set, bnd) )
8127  posinf = TRUE;
8128  else if( SCIPsetIsInfinity(set, -bnd) )
8129  neginf = TRUE;
8130  else
8131  ub += var->data.multaggr.scalars[i] * bnd;
8132  }
8133  else
8134  {
8135  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8136 
8137  if( SCIPsetIsInfinity(set, -bnd) )
8138  posinf = TRUE;
8139  else if( SCIPsetIsInfinity(set, bnd) )
8140  neginf = TRUE;
8141  else
8142  ub += var->data.multaggr.scalars[i] * bnd;
8143  }
8144 
8145  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8146  * variable
8147  */
8148  if( posinf )
8149  return SCIPvarGetUbGlobal(var);
8150  }
8151 
8152  /* if negative infinity flag was set to true return -infinity */
8153  if( neginf )
8154  return -SCIPsetInfinity(set);
8155 
8156  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8157 }
8158 
8159 /** adds a hole to the original domain of the variable */
8161  SCIP_VAR* var, /**< problem variable */
8162  BMS_BLKMEM* blkmem, /**< block memory */
8163  SCIP_SET* set, /**< global SCIP settings */
8164  SCIP_Real left, /**< left bound of open interval in new hole */
8165  SCIP_Real right /**< right bound of open interval in new hole */
8166  )
8167 {
8168  SCIP_Bool added;
8169 
8170  assert(var != NULL);
8171  assert(!SCIPvarIsTransformed(var));
8173  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8174  assert(set != NULL);
8175  assert(var->scip == set->scip);
8176  assert(set->stage == SCIP_STAGE_PROBLEM);
8177 
8178  SCIPdebugMessage("adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8179 
8180  if( SCIPsetIsEQ(set, left, right) )
8181  return SCIP_OKAY;
8182 
8183  /* the interval should not be empty */
8184  assert(SCIPsetIsLT(set, left, right));
8185 
8186  /* the the interval bound should already be adjusted */
8187  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8188  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8189 
8190  /* the the interval should lay between the lower and upper bound */
8191  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8192  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8193 
8194  /* add domain hole */
8195  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8196 
8197  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8198  if( added )
8199  {
8200  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8201  }
8202 
8203  /**@todo add hole in parent and child variables (just like with bound changes);
8204  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8205  */
8206 
8207  return SCIP_OKAY;
8208 }
8209 
8210 /** performs the current add of domain, changes all parents accordingly */
8211 static
8213  SCIP_VAR* var, /**< problem variable */
8214  BMS_BLKMEM* blkmem, /**< block memory */
8215  SCIP_SET* set, /**< global SCIP settings */
8216  SCIP_STAT* stat, /**< problem statistics */
8217  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8218  SCIP_Real left, /**< left bound of open interval in new hole */
8219  SCIP_Real right, /**< right bound of open interval in new hole */
8220  SCIP_Bool* added /**< pointer to store whether the hole was added */
8221  )
8222 {
8223  SCIP_VAR* parentvar;
8224  SCIP_Real newlb;
8225  SCIP_Real newub;
8226  int i;
8227 
8228  assert(var != NULL);
8229  assert(added != NULL);
8230  assert(blkmem != NULL);
8231 
8232  /* the interval should not be empty */
8233  assert(SCIPsetIsLT(set, left, right));
8234 
8235  /* the interval bound should already be adjusted */
8236  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8237  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8238 
8239  /* the interval should lay between the lower and upper bound */
8240  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8241  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8242 
8243  /* @todo add debugging mechanism for holes when using a debugging solution */
8244 
8245  /* add hole to hole list */
8246  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8247 
8248  /* check if the hole is redundant */
8249  if( !(*added) )
8250  return SCIP_OKAY;
8251 
8252  /* current bounds */
8253  newlb = var->glbdom.lb;
8254  newub = var->glbdom.ub;
8255 
8256  /* merge domain holes */
8257  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8258 
8259  /* the bound should not be changed */
8260  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8261  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8262 
8263  /* issue bound change event */
8264  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8265  if( var->eventfilter != NULL )
8266  {
8267  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8268  }
8269 
8270  /* process parent variables */
8271  for( i = 0; i < var->nparentvars; ++i )
8272  {
8273  SCIP_Real parentnewleft;
8274  SCIP_Real parentnewright;
8275  SCIP_Bool localadded;
8276 
8277  parentvar = var->parentvars[i];
8278  assert(parentvar != NULL);
8279 
8280  switch( SCIPvarGetStatus(parentvar) )
8281  {
8283  parentnewleft = left;
8284  parentnewright = right;
8285  break;
8286 
8287  case SCIP_VARSTATUS_COLUMN:
8288  case SCIP_VARSTATUS_LOOSE:
8289  case SCIP_VARSTATUS_FIXED:
8291  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8292  return SCIP_INVALIDDATA;
8293 
8294  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8295  assert(parentvar->data.aggregate.var == var);
8296 
8297  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8298  {
8299  /* a > 0 -> change upper bound of x */
8300  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8301  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8302  }
8303  else
8304  {
8305  /* a < 0 -> change lower bound of x */
8306  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8307 
8308  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8309  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8310  }
8311  break;
8312 
8313  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8314  assert(parentvar->negatedvar != NULL);
8315  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8316  assert(parentvar->negatedvar->negatedvar == parentvar);
8317 
8318  parentnewright = -left + parentvar->data.negate.constant;
8319  parentnewleft = -right + parentvar->data.negate.constant;
8320  break;
8321 
8322  default:
8323  SCIPerrorMessage("unknown variable status\n");
8324  return SCIP_INVALIDDATA;
8325  }
8326 
8327  SCIPdebugMessage("add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8328 
8329  /* perform hole added for parent variable */
8330  assert(blkmem != NULL);
8331  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8332  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8333  parentnewleft, parentnewright, &localadded) );
8334  assert(localadded);
8335  }
8336 
8337  return SCIP_OKAY;
8338 }
8339 
8340 /** adds a hole to the variable's global and local domain */
8342  SCIP_VAR* var, /**< problem variable */
8343  BMS_BLKMEM* blkmem, /**< block memory */
8344  SCIP_SET* set, /**< global SCIP settings */
8345  SCIP_STAT* stat, /**< problem statistics */
8346  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8347  SCIP_Real left, /**< left bound of open interval in new hole */
8348  SCIP_Real right, /**< right bound of open interval in new hole */
8349  SCIP_Bool* added /**< pointer to store whether the hole was added */
8350  )
8351 {
8352  SCIP_Real childnewleft;
8353  SCIP_Real childnewright;
8354 
8355  assert(var != NULL);
8356  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8357  assert(blkmem != NULL);
8358  assert(added != NULL);
8359 
8360  SCIPdebugMessage("adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8361 
8362  /* the interval should not be empty */
8363  assert(SCIPsetIsLT(set, left, right));
8364 
8365  /* the the interval bound should already be adjusted */
8366  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8367  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8368 
8369  /* the the interval should lay between the lower and upper bound */
8370  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8371  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8372 
8373  /* change bounds of attached variables */
8374  switch( SCIPvarGetStatus(var) )
8375  {
8377  if( var->data.original.transvar != NULL )
8378  {
8379  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8380  left, right, added) );
8381  }
8382  else
8383  {
8384  assert(set->stage == SCIP_STAGE_PROBLEM);
8385 
8386  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8387  if( *added )
8388  {
8389  SCIP_Bool localadded;
8390 
8391  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8392  }
8393  }
8394  break;
8395 
8396  case SCIP_VARSTATUS_COLUMN:
8397  case SCIP_VARSTATUS_LOOSE:
8398  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8399  if( *added )
8400  {
8401  SCIP_Bool localadded;
8402 
8403  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8404  }
8405  break;
8406 
8407  case SCIP_VARSTATUS_FIXED:
8408  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8409  return SCIP_INVALIDDATA;
8410 
8411  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8412  assert(var->data.aggregate.var != NULL);
8413 
8414  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8415  {
8416  /* a > 0 -> change lower bound of y */
8417  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8418  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8419  }
8420  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8421  {
8422  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8423  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8424  }
8425  else
8426  {
8427  SCIPerrorMessage("scalar is zero in aggregation\n");
8428  return SCIP_INVALIDDATA;
8429  }
8430  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8431  childnewleft, childnewright, added) );
8432  break;
8433 
8435  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8436  return SCIP_INVALIDDATA;
8437 
8438  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8439  assert(var->negatedvar != NULL);
8441  assert(var->negatedvar->negatedvar == var);
8442 
8443  childnewright = -left + var->data.negate.constant;
8444  childnewleft = -right + var->data.negate.constant;
8445 
8446  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8447  childnewleft, childnewright, added) );
8448  break;
8449 
8450  default:
8451  SCIPerrorMessage("unknown variable status\n");
8452  return SCIP_INVALIDDATA;
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, or NULL */
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 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 the interval should lay between the lower and upper bound */
8488  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8489  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8490 
8491  /* add hole to hole list */
8492  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8493 
8494  /* check if the hole is redundant */
8495  if( !(*added) )
8496  return SCIP_OKAY;
8497 
8498  /* current bounds */
8499  newlb = var->locdom.lb;
8500  newub = var->locdom.ub;
8501 
8502  /* merge domain holes */
8503  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8504 
8505  /* the bound should not be changed */
8506  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8507  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8508 
8509 #if 0
8510  /* issue bound change event */
8511  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8512  if( var->eventfilter != NULL )
8513  {
8514  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8515  }
8516 #endif
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  SCIPdebugMessage("add local 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( varProcessAddHoleLocal(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 current 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  SCIPdebugMessage("adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8604 
8605  assert(var != NULL);
8606  assert(set != NULL);
8607  assert(var->scip == set->scip);
8608  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8609  assert(blkmem != NULL);
8610  assert(added != NULL);
8611 
8612  /* the interval should not be empty */
8613  assert(SCIPsetIsLT(set, left, right));
8614 
8615  /* the the interval bound should already be adjusted */
8616  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8617  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8618 
8619  /* the the interval should lay between the lower and upper bound */
8620  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8621  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8622 
8623  /* change bounds of attached variables */
8624  switch( SCIPvarGetStatus(var) )
8625  {
8627  if( var->data.original.transvar != NULL )
8628  {
8629  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8630  left, right, added) );
8631  }
8632  else
8633  {
8634  assert(set->stage == SCIP_STAGE_PROBLEM);
8635 
8636  stat->domchgcount++;
8637  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8638  }
8639  break;
8640 
8641  case SCIP_VARSTATUS_COLUMN:
8642  case SCIP_VARSTATUS_LOOSE:
8643  stat->domchgcount++;
8644  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8645  break;
8646 
8647  case SCIP_VARSTATUS_FIXED:
8648  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8649  return SCIP_INVALIDDATA;
8650 
8651  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8652  assert(var->data.aggregate.var != NULL);
8653 
8654  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8655  {
8656  /* a > 0 -> change lower bound of y */
8657  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8658  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8659  }
8660  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8661  {
8662  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8663  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8664  }
8665  else
8666  {
8667  SCIPerrorMessage("scalar is zero in aggregation\n");
8668  return SCIP_INVALIDDATA;
8669  }
8670  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8671  childnewleft, childnewright, added) );
8672  break;
8673 
8675  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8676  return SCIP_INVALIDDATA;
8677 
8678  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8679  assert(var->negatedvar != NULL);
8681  assert(var->negatedvar->negatedvar == var);
8682 
8683  childnewright = -left + var->data.negate.constant;
8684  childnewleft = -right + var->data.negate.constant;
8685 
8686  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8687  break;
8688 
8689  default:
8690  SCIPerrorMessage("unknown variable status\n");
8691  return SCIP_INVALIDDATA;
8692  }
8693 
8694  return SCIP_OKAY;
8695 }
8696 
8697 /** resets the global and local bounds of original variable to their original values */
8699  SCIP_VAR* var, /**< problem variable */
8700  BMS_BLKMEM* blkmem, /**< block memory */
8701  SCIP_SET* set, /**< global SCIP settings */
8702  SCIP_STAT* stat /**< problem statistics */
8703  )
8704 {
8705  assert(var != NULL);
8706  assert(set != NULL);
8707  assert(var->scip == set->scip);
8708  assert(SCIPvarIsOriginal(var));
8709  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8710  * the transformed variable has been fixed */
8711  assert(SCIPvarGetTransVar(var) == NULL);
8712 
8713  /* copy the original bounds back to the global and local bounds */
8714  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8715  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8716  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8717  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8718 
8719  /* free the global and local holelists and duplicate the original ones */
8720  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8721  holelistFree(&var->glbdom.holelist, blkmem);
8722  holelistFree(&var->locdom.holelist, blkmem);
8723  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8724  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8725 
8726  return SCIP_OKAY;
8727 }
8728 
8729 /** issues a IMPLADDED event on the given variable */
8730 static
8732  SCIP_VAR* var, /**< problem variable to change */
8733  BMS_BLKMEM* blkmem, /**< block memory */
8734  SCIP_SET* set, /**< global SCIP settings */
8735  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8736  )
8737 {
8738  SCIP_EVENT* event;
8739 
8740  assert(var != NULL);
8741 
8742  /* issue IMPLADDED event on variable */
8743  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8744  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8745 
8746  return SCIP_OKAY;
8747 }
8748 
8749 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8750 static
8752  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8753  BMS_BLKMEM* blkmem, /**< block memory */
8754  SCIP_SET* set, /**< global SCIP settings */
8755  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8756  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8757  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8758  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8759  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8760  )
8761 {
8762  SCIP_Bool added;
8763 
8764  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8765  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
8766  * variable of the aggregated variable might be the same as the one its gets aggregated too.
8767  *
8768  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
8769  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
8770  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
8771  * variable bound can be ignored.
8772  *
8773  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
8774  * equivalence of the variables should be checked here.
8775  */
8776  if( var == vbvar )
8777  {
8778  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
8779  * can be checked via the global bounds of the variable */
8780 #ifndef NDEBUG
8781  SCIP_Real lb;
8782  SCIP_Real ub;
8783 
8784  lb = SCIPvarGetLbGlobal(var);
8785  ub = SCIPvarGetUbGlobal(var);
8786 
8787  if(vbtype == SCIP_BOUNDTYPE_LOWER)
8788  {
8789  if( vbcoef > 0.0 )
8790  {
8791  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
8792  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
8793  }
8794  else
8795  {
8796  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
8797  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
8798  }
8799  }
8800  else
8801  {
8802  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
8803  if( vbcoef > 0.0 )
8804  {
8805  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
8806  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
8807  }
8808  else
8809  {
8810  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
8811  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
8812  }
8813  }
8814 #endif
8815  SCIPdebugMessage("redundant variable bound: <%s> %s %g<%s> %+g\n",
8816  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8817 
8818  return SCIP_OKAY;
8819  }
8820 
8821  SCIPdebugMessage("adding variable bound: <%s> %s %g<%s> %+g\n",
8822  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8823 
8824  /* check variable bound on debugging solution */
8825  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
8826 
8827  /* perform the addition */
8828  if( vbtype == SCIP_BOUNDTYPE_LOWER )
8829  {
8830  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8831  }
8832  else
8833  {
8834  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8835  }
8836  var->closestvblpcount = -1;
8837 
8838  if( added )
8839  {
8840  /* issue IMPLADDED event */
8841  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
8842  }
8843 
8844  return SCIP_OKAY;
8845 }
8846 
8847 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
8848 static
8849 void checkImplic(
8850  SCIP_SET* set, /**< global SCIP settings */
8851  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8852  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8853  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8854  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
8855  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
8856  )
8857 {
8858  SCIP_Real impllb;
8859  SCIP_Real implub;
8860 
8861  assert(redundant != NULL);
8862  assert(infeasible != NULL);
8863 
8864  impllb = SCIPvarGetLbGlobal(implvar);
8865  implub = SCIPvarGetUbGlobal(implvar);
8866  if( impltype == SCIP_BOUNDTYPE_LOWER )
8867  {
8868  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
8869  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
8870  }
8871  else
8872  {
8873  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
8874  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
8875  }
8876 }
8877 
8878 /** applies the given implication, if it is not redundant */
8879 static
8881  BMS_BLKMEM* blkmem, /**< block memory */
8882  SCIP_SET* set, /**< global SCIP settings */
8883  SCIP_STAT* stat, /**< problem statistics */
8884  SCIP_PROB* transprob, /**< transformed problem */
8885  SCIP_PROB* origprob, /**< original problem */
8886  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
8887  SCIP_LP* lp, /**< current LP data */
8888  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8889  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8890  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8891  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8892  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8893  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
8894  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
8895  )
8896 {
8897  SCIP_Real implub;
8898  SCIP_Real impllb;
8899 
8900  assert(infeasible != NULL);
8901 
8902  *infeasible = FALSE;
8903 
8904  implub = SCIPvarGetUbGlobal(implvar);
8905  impllb = SCIPvarGetLbGlobal(implvar);
8906  if( impltype == SCIP_BOUNDTYPE_LOWER )
8907  {
8908  if( SCIPsetIsFeasGT(set, implbound, implub) )
8909  {
8910  /* the implication produces a conflict: the problem is infeasible */
8911  *infeasible = TRUE;
8912  }
8913  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
8914  {
8915  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8916  * with the local bound, in this case we need to store the bound change as pending bound change
8917  */
8918  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8919  {
8920  assert(tree != NULL);
8921  assert(transprob != NULL);
8922  assert(SCIPprobIsTransformed(transprob));
8923 
8924  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8925  tree, lp, branchcand, eventqueue, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
8926  }
8927  else
8928  {
8929  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, implbound) );
8930  }
8931 
8932  if( nbdchgs != NULL )
8933  (*nbdchgs)++;
8934  }
8935  }
8936  else
8937  {
8938  if( SCIPsetIsFeasLT(set, implbound, impllb) )
8939  {
8940  /* the implication produces a conflict: the problem is infeasible */
8941  *infeasible = TRUE;
8942  }
8943  else if( SCIPsetIsFeasLT(set, implbound, implub) )
8944  {
8945  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8946  * with the local bound, in this case we need to store the bound change as pending bound change
8947  */
8948  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8949  {
8950  assert(tree != NULL);
8951  assert(transprob != NULL);
8952  assert(SCIPprobIsTransformed(transprob));
8953 
8954  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8955  tree, lp, branchcand, eventqueue, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
8956  }
8957  else
8958  {
8959  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, implbound) );
8960  }
8961 
8962  if( nbdchgs != NULL )
8963  (*nbdchgs)++;
8964  }
8965  }
8966 
8967  return SCIP_OKAY;
8968 }
8969 
8970 /** actually performs the addition of an implication to the variable's implication arrays,
8971  * and adds the corresponding implication or variable bound to the implied variable;
8972  * if the implication is conflicting, the variable is fixed to the opposite value;
8973  * if the variable is already fixed to the given value, the implication is performed immediately;
8974  * if the implication is redundant with respect to the variables' global bounds, it is ignored
8975  */
8976 static
8978  SCIP_VAR* var, /**< problem variable */
8979  BMS_BLKMEM* blkmem, /**< block memory */
8980  SCIP_SET* set, /**< global SCIP settings */
8981  SCIP_STAT* stat, /**< problem statistics */
8982  SCIP_PROB* transprob, /**< transformed problem */
8983  SCIP_PROB* origprob, /**< original problem */
8984  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
8985  SCIP_LP* lp, /**< current LP data */
8986  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8987  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8988  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
8989  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8990  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8991  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8992  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
8993  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
8994  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
8995  SCIP_Bool* added /**< pointer to store whether an implication was added */
8996  )
8997 {
8998  SCIP_Bool redundant;
8999  SCIP_Bool conflict;
9000 
9001  assert(var != NULL);
9002  assert(SCIPvarIsActive(var));
9004  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9005  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9006  assert(infeasible != NULL);
9007  assert(added != NULL);
9008 
9009  /* check implication on debugging solution */
9010  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9011 
9012  *infeasible = FALSE;
9013  *added = FALSE;
9014 
9015  /* check, if the implication is redundant or infeasible */
9016  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9017  assert(!redundant || !conflict);
9018  if( redundant )
9019  return SCIP_OKAY;
9020 
9021  if( var == implvar )
9022  {
9023  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9024  * x == varfixing => x < 0 or x > 1
9025  */
9026  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9027  conflict = TRUE;
9028  else
9029  {
9030  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9031  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9032  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9033  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9034  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9035  if( !conflict )
9036  return SCIP_OKAY;
9037  }
9038  }
9039 
9040  /* check, if the variable is already fixed */
9041  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9042  {
9043  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9044  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9045  {
9046  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9047  implvar, impltype, implbound, infeasible, nbdchgs) );
9048  }
9049  return SCIP_OKAY;
9050  }
9051 
9052  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9053  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9054 
9055  if( !conflict )
9056  {
9057  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9058 
9059  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9060  SCIPdebugMessage("adding implication: <%s> == %u ==> <%s> %s %g\n",
9061  SCIPvarGetName(var), varfixing,
9062  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9063  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9064  isshortcut, &conflict, added) );
9065  }
9066  assert(!conflict || !(*added));
9067 
9068  /* on conflict, fix the variable to the opposite value */
9069  if( conflict )
9070  {
9071  SCIPdebugMessage(" -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9072 
9073  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9074  * with the local bound, in this case we need to store the bound change as pending bound change
9075  */
9076  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9077  {
9078  assert(tree != NULL);
9079  assert(transprob != NULL);
9080  assert(SCIPprobIsTransformed(transprob));
9081 
9082  if( varfixing )
9083  {
9084  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9085  tree, lp, branchcand, eventqueue, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9086  }
9087  else
9088  {
9089  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9090  tree, lp, branchcand, eventqueue, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9091  }
9092  }
9093  else
9094  {
9095  if( varfixing )
9096  {
9097  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, 0.0) );
9098  }
9099  else
9100  {
9101  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, 1.0) );
9102  }
9103  }
9104  if( nbdchgs != NULL )
9105  (*nbdchgs)++;
9106 
9107  return SCIP_OKAY;
9108  }
9109  else if( *added )
9110  {
9111  /* issue IMPLADDED event */
9112  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9113  }
9114  else
9115  {
9116  /* the implication was redundant: the inverse is also redundant */
9117  return SCIP_OKAY;
9118  }
9119 
9120  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9121 
9122  /* check, whether implied variable is binary */
9123  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9124  {
9125  SCIP_Bool inverseadded;
9126 
9127  assert(SCIPsetIsEQ(set, implbound, 0.0) == (impltype == SCIP_BOUNDTYPE_UPPER));
9128  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9129 
9130  /* add inverse implication y == 0/1 -> x == 0/1 to the implications list of y:
9131  * x == 0 -> y == 0 <-> y == 1 -> x == 1
9132  * x == 1 -> y == 0 <-> y == 1 -> x == 0
9133  * x == 0 -> y == 1 <-> y == 0 -> x == 1
9134  * x == 1 -> y == 1 <-> y == 0 -> x == 0
9135  */
9136  SCIPdebugMessage("adding inverse implication: <%s> == %d ==> <%s> == %d\n",
9137  SCIPvarGetName(implvar), (impltype == SCIP_BOUNDTYPE_UPPER), SCIPvarGetName(var), !varfixing);
9138  SCIP_CALL( SCIPimplicsAdd(&implvar->implics, blkmem, set, stat,
9139  (impltype == SCIP_BOUNDTYPE_UPPER), var, varfixing ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER,
9140  varfixing ? 0.0 : 1.0, isshortcut, &conflict, &inverseadded) );
9141  assert(inverseadded == !conflict); /* if there is no conflict, the implication must not be redundant */
9142 
9143  /* on conflict, fix the variable to the opposite value */
9144  if( conflict )
9145  {
9146  SCIPdebugMessage(" -> implication yields a conflict: fix <%s> == %d\n",
9147  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_LOWER);
9148 
9149  /* remove the original implication (which is now redundant due to the fixing of the implvar) */
9150  SCIPdebugMessage(" -> deleting implication: <%s> == %u ==> <%s> %s %g\n",
9151  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=",
9152  implbound);
9153  SCIP_CALL( SCIPimplicsDel(&var->implics, blkmem, set, varfixing, implvar, impltype) );
9154 
9155  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9156  * with the local bound, in this case we need to store the bound change as pending bound change
9157  */
9158  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9159  {
9160  assert(tree != NULL);
9161  assert(transprob != NULL);
9162  assert(SCIPprobIsTransformed(transprob));
9163 
9164  /* fix implvar */
9165  if( impltype == SCIP_BOUNDTYPE_UPPER )
9166  {
9167  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9168  tree, lp, branchcand, eventqueue, implvar, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9169  }
9170  else
9171  {
9172  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9173  tree, lp, branchcand, eventqueue, implvar, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9174  }
9175  }
9176  else
9177  {
9178  /* fix implvar */
9179  if( impltype == SCIP_BOUNDTYPE_UPPER )
9180  {
9181  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, 0.0) );
9182  }
9183  else
9184  {
9185  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, 1.0) );
9186  }
9187  }
9188 
9189  if( nbdchgs != NULL )
9190  (*nbdchgs)++;
9191  }
9192  else if( inverseadded )
9193  {
9194  /* issue IMPLADDED event */
9195  SCIP_CALL( varEventImplAdded(implvar, blkmem, set, eventqueue) );
9196  }
9197  }
9198  else
9199  {
9200  SCIP_Real lb;
9201  SCIP_Real ub;
9202 
9203  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9204  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9205  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9206  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9207  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9208  * for numerical reasons, ignore variable bounds with large absolute coefficient
9209  */
9210  lb = SCIPvarGetLbGlobal(implvar);
9211  ub = SCIPvarGetUbGlobal(implvar);
9212  if( impltype == SCIP_BOUNDTYPE_UPPER )
9213  {
9214  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9215  {
9216  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9217  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9218  }
9219  }
9220  else
9221  {
9222  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9223  {
9224  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9225  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9226  }
9227  }
9228  }
9229 
9230  return SCIP_OKAY;
9231 }
9232 
9233 /** adds transitive closure for binary implication x = a -> y = b */
9234 static
9236  SCIP_VAR* var, /**< problem variable */
9237  BMS_BLKMEM* blkmem, /**< block memory */
9238  SCIP_SET* set, /**< global SCIP settings */
9239  SCIP_STAT* stat, /**< problem statistics */
9240  SCIP_PROB* transprob, /**< transformed problem */
9241  SCIP_PROB* origprob, /**< original problem */
9242  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9243  SCIP_LP* lp, /**< current LP data */
9244  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9245  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9246  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9247  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9248  SCIP_Bool implvarfixing, /**< fixing b in implication */
9249  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9250  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9251  )
9252 {
9253  SCIP_VAR** implvars;
9254  SCIP_BOUNDTYPE* impltypes;
9255  SCIP_Real* implbounds;
9256  int nimpls;
9257  int i;
9258 
9259  *infeasible = FALSE;
9260 
9261  /* binary variable: implications of implvar */
9262  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9263  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9264  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9265  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9266 
9267  /* if variable has too many implications, the implication graph may become too dense */
9268  if( nimpls > MAXIMPLSCLOSURE )
9269  return SCIP_OKAY;
9270 
9271  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9272  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9273  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9274  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9275  * only thing that can happen is that we add the same implication twice - this does no harm
9276  */
9277  i = nimpls-1;
9278  while ( i >= 0 && !(*infeasible) )
9279  {
9280  SCIP_Bool added;
9281 
9282  assert(implvars[i] != implvar);
9283 
9284  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9285  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9286  */
9287  if( SCIPvarIsActive(implvars[i]) )
9288  {
9289  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9290  varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9291  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9292  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9293  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9294  }
9295  --i;
9296  }
9297 
9298  return SCIP_OKAY;
9299 }
9300 
9301 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9302  * implication to the variable's implication list;
9303  * if the implication is conflicting, the variable is fixed to the opposite value;
9304  * if the variable is already fixed to the given value, the implication is performed immediately;
9305  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9306  */
9307 static
9309  SCIP_VAR* var, /**< problem variable */
9310  BMS_BLKMEM* blkmem, /**< block memory */
9311  SCIP_SET* set, /**< global SCIP settings */
9312  SCIP_STAT* stat, /**< problem statistics */
9313  SCIP_PROB* transprob, /**< transformed problem */
9314  SCIP_PROB* origprob, /**< original problem */
9315  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9316  SCIP_LP* lp, /**< current LP data */
9317  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9318  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9319  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9320  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9321  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9322  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9323  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9324  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9325  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9326  )
9327 {
9328  SCIP_Bool added;
9329 
9330  assert(var != NULL);
9331  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9332  assert(SCIPvarIsActive(var));
9333  assert(implvar != NULL);
9334  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9335  assert(infeasible != NULL);
9336 
9337  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9338  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9339  varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9340  if( *infeasible || var == implvar || !transitive || !added )
9341  return SCIP_OKAY;
9342 
9343  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9344 
9345  /* add transitive closure */
9346  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9347  {
9348  SCIP_Bool implvarfixing;
9349 
9350  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9351 
9352  /* binary variable: implications of implvar */
9353  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
9354  eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9355 
9356  /* inverse implication */
9357  if( !(*infeasible) )
9358  {
9359  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, lp,
9360  branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9361  }
9362  }
9363  else
9364  {
9365  /* non-binary variable: variable lower bounds of implvar */
9366  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9367  {
9368  SCIP_VAR** vlbvars;
9369  SCIP_Real* vlbcoefs;
9370  SCIP_Real* vlbconstants;
9371  int nvlbvars;
9372  int i;
9373 
9374  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9375  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9376  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9377  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9378 
9379  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9380  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9381  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9382  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9383  * is that we add the same implication twice - this does no harm
9384  */
9385  i = nvlbvars-1;
9386  while ( i >= 0 && !(*infeasible) )
9387  {
9388  assert(vlbvars[i] != implvar);
9389  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9390 
9391  /* we have x == varfixing -> y <= b and y >= c*z + d:
9392  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9393  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9394  *
9395  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9396  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9397  * aggregation variable (the one which will stay active);
9398  *
9399  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9400  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9401  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9402  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9403  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9404  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9405  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9406  * have to explicitly check that the active variable has not a variable status
9407  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9408  */
9409  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9410  {
9411  SCIP_Real vbimplbound;
9412 
9413  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9414  if( vlbcoefs[i] >= 0.0 )
9415  {
9416  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9417  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9418  varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE, infeasible, nbdchgs, &added) );
9419  }
9420  else
9421  {
9422  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9423  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9424  varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE, infeasible, nbdchgs, &added) );
9425  }
9426  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9427  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9428  }
9429  --i;
9430  }
9431  }
9432 
9433  /* non-binary variable: variable upper bounds of implvar */
9434  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9435  {
9436  SCIP_VAR** vubvars;
9437  SCIP_Real* vubcoefs;
9438  SCIP_Real* vubconstants;
9439  int nvubvars;
9440  int i;
9441 
9442  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9443  vubvars = SCIPvboundsGetVars(implvar->vubs);
9444  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9445  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9446 
9447  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9448  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9449  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9450  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9451  * is that we add the same implication twice - this does no harm
9452  */
9453  i = nvubvars-1;
9454  while ( i >= 0 && !(*infeasible) )
9455  {
9456  assert(vubvars[i] != implvar);
9457  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9458 
9459  /* we have x == varfixing -> y >= b and y <= c*z + d:
9460  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9461  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9462  *
9463  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9464  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9465  * aggregation variable (the one which will stay active);
9466  *
9467  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9468  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9469  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9470  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9471  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9472  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9473  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9474  * have to explicitly check that the active variable has not a variable status
9475  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9476  */
9477  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9478  {
9479  SCIP_Real vbimplbound;
9480 
9481  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9482  if( vubcoefs[i] >= 0.0 )
9483  {
9484  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9485  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9486  varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE, infeasible, nbdchgs, &added) );
9487  }
9488  else
9489  {
9490  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9491  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
9492  varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE, infeasible, nbdchgs, &added) );
9493  }
9494  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9495  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9496  }
9497  --i;
9498  }
9499  }
9500  }
9501 
9502  return SCIP_OKAY;
9503 }
9504 
9505 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9506  * if z is binary, the corresponding valid implication for z is also added;
9507  * improves the global bounds of the variable and the vlb variable if possible
9508  */
9510  SCIP_VAR* var, /**< problem variable */
9511  BMS_BLKMEM* blkmem, /**< block memory */
9512  SCIP_SET* set, /**< global SCIP settings */
9513  SCIP_STAT* stat, /**< problem statistics */
9514  SCIP_PROB* transprob, /**< transformed problem */
9515  SCIP_PROB* origprob, /**< original problem */
9516  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
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_VAR* vlbvar, /**< variable z in x >= b*z + d */
9522  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9523  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9524  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9525  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9526  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9527  )
9528 {
9529  assert(var != NULL);
9530  assert(set != NULL);
9531  assert(var->scip == set->scip);
9532  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9533  assert(infeasible != NULL);
9534 
9535  SCIPdebugMessage("adding variable lower bound <%s> >= %g<%s> + %g\n",
9536  SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9537 
9538  *infeasible = FALSE;
9539  if( nbdchgs != NULL )
9540  *nbdchgs = 0;
9541 
9542  switch( SCIPvarGetStatus(var) )
9543  {
9545  assert(var->data.original.transvar != NULL);
9546  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, lp,
9547  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9548  break;
9549 
9550  case SCIP_VARSTATUS_COLUMN:
9551  case SCIP_VARSTATUS_LOOSE:
9552  case SCIP_VARSTATUS_FIXED:
9553  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9554  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9555  SCIPdebugMessage(" -> transformed to variable lower bound <%s> >= %g<%s> + %g\n",
9556  SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9557 
9558  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9559  if( SCIPsetIsZero(set, vlbcoef) )
9560  {
9561  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9562  *infeasible = TRUE;
9563  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9564  {
9565  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9566  * with the local bound, in this case we need to store the bound change as pending bound change
9567  */
9568  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9569  {
9570  assert(tree != NULL);
9571  assert(transprob != NULL);
9572  assert(SCIPprobIsTransformed(transprob));
9573 
9574  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9575  tree, lp, branchcand, eventqueue, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9576  }
9577  else
9578  {
9579  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, vlbconstant) );
9580  }
9581 
9582  if( nbdchgs != NULL )
9583  (*nbdchgs)++;
9584  }
9585  }
9586  else if( SCIPvarIsActive(vlbvar) )
9587  {
9588  SCIP_Real xlb;
9589  SCIP_Real xub;
9590  SCIP_Real zlb;
9591  SCIP_Real zub;
9592  SCIP_Real minvlb;
9593  SCIP_Real maxvlb;
9594 
9596  assert(vlbcoef != 0.0);
9597 
9598  minvlb = -SCIPsetInfinity(set);
9599  maxvlb = -SCIPsetInfinity(set);
9600 
9601  xlb = SCIPvarGetLbGlobal(var);
9602  xub = SCIPvarGetUbGlobal(var);
9603  zlb = SCIPvarGetLbGlobal(vlbvar);
9604  zub = SCIPvarGetUbGlobal(vlbvar);
9605 
9606  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9607  if( vlbcoef >= 0.0 )
9608  {
9609  SCIP_Real newzub;
9610 
9611  if( !SCIPsetIsInfinity(set, xub) )
9612  {
9613  /* x >= b*z + d -> z <= (x-d)/b */
9614  newzub = (xub - vlbconstant)/vlbcoef;
9615  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9616  {
9617  *infeasible = TRUE;
9618  return SCIP_OKAY;
9619  }
9620  if( SCIPsetIsFeasLT(set, newzub, zub) )
9621  {
9622  /* bound might be adjusted due to integrality condition */
9623  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9624 
9625  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9626  * with the local bound, in this case we need to store the bound change as pending bound change
9627  */
9628  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9629  {
9630  assert(tree != NULL);
9631  assert(transprob != NULL);
9632  assert(SCIPprobIsTransformed(transprob));
9633 
9634  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9635  tree, lp, branchcand, eventqueue, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9636  }
9637  else
9638  {
9639  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, newzub) );
9640  }
9641  zub = newzub;
9642 
9643  if( nbdchgs != NULL )
9644  (*nbdchgs)++;
9645  }
9646  maxvlb = vlbcoef * zub + vlbconstant;
9647  if( !SCIPsetIsInfinity(set, -zlb) )
9648  minvlb = vlbcoef * zlb + vlbconstant;
9649  }
9650  else
9651  {
9652  if( !SCIPsetIsInfinity(set, zub) )
9653  maxvlb = vlbcoef * zub + vlbconstant;
9654  if( !SCIPsetIsInfinity(set, -zlb) )
9655  minvlb = vlbcoef * zlb + vlbconstant;
9656  }
9657  }
9658  else
9659  {
9660  SCIP_Real newzlb;
9661 
9662  if( !SCIPsetIsInfinity(set, xub) )
9663  {
9664  /* x >= b*z + d -> z >= (x-d)/b */
9665  newzlb = (xub - vlbconstant)/vlbcoef;
9666  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9667  {
9668  *infeasible = TRUE;
9669  return SCIP_OKAY;
9670  }
9671  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9672  {
9673  /* bound might be adjusted due to integrality condition */
9674  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9675 
9676  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9677  * with the local bound, in this case we need to store the bound change as pending bound change
9678  */
9679  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9680  {
9681  assert(tree != NULL);
9682  assert(transprob != NULL);
9683  assert(SCIPprobIsTransformed(transprob));
9684 
9685  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9686  tree, lp, branchcand, eventqueue, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9687  }
9688  else
9689  {
9690  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, newzlb) );
9691  }
9692  zlb = newzlb;
9693 
9694  if( nbdchgs != NULL )
9695  (*nbdchgs)++;
9696  }
9697  maxvlb = vlbcoef * zlb + vlbconstant;
9698  if( !SCIPsetIsInfinity(set, zub) )
9699  minvlb = vlbcoef * zub + vlbconstant;
9700  }
9701  else
9702  {
9703  if( !SCIPsetIsInfinity(set, -zlb) )
9704  maxvlb = vlbcoef * zlb + vlbconstant;
9705  if( !SCIPsetIsInfinity(set, zub) )
9706  minvlb = vlbcoef * zub + vlbconstant;
9707  }
9708  }
9709  if( maxvlb < minvlb )
9710  maxvlb = minvlb;
9711 
9712  /* adjust bounds due to integrality of variable */
9713  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9714  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9715 
9716  /* check bounds for feasibility */
9717  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9718  {
9719  *infeasible = TRUE;
9720  return SCIP_OKAY;
9721  }
9722  /* improve global lower bound of variable */
9723  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9724  {
9725  /* bound might be adjusted due to integrality condition */
9726  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9727 
9728  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9729  * with the local bound, in this case we need to store the bound change as pending bound change
9730  */
9731  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9732  {
9733  assert(tree != NULL);
9734  assert(transprob != NULL);
9735  assert(SCIPprobIsTransformed(transprob));
9736 
9737  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9738  tree, lp, branchcand, eventqueue, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9739  }
9740  else
9741  {
9742  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, minvlb) );
9743  }
9744  xlb = minvlb;
9745 
9746  if( nbdchgs != NULL )
9747  (*nbdchgs)++;
9748  }
9749  minvlb = xlb;
9750 
9751  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9752  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9753  {
9754  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9755  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9756  */
9757 
9758  assert(!SCIPsetIsInfinity(set, -maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9759 
9760  if( vlbcoef >= 0.0 )
9761  {
9762  vlbcoef = maxvlb - minvlb;
9763  vlbconstant = minvlb;
9764  }
9765  else
9766  {
9767  vlbcoef = minvlb - maxvlb;
9768  vlbconstant = maxvlb;
9769  }
9770  }
9771 
9772  /* add variable bound to the variable bounds list */
9773  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9774  {
9775  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9776  assert(!SCIPsetIsZero(set, vlbcoef));
9777 
9778  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9779  * list, thereby also adding the variable bound (or implication) to the other variable
9780  */
9781  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9782  {
9783  /* add corresponding implication:
9784  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9785  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9786  */
9787  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
9788  eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive, infeasible, nbdchgs) );
9789  }
9790  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9791  {
9792  /* add corresponding implication:
9793  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9794  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9795  */
9796  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
9797  eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
9798  -vlbconstant/vlbcoef, transitive, infeasible, nbdchgs) );
9799  }
9800  else
9801  {
9802  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
9803  }
9804  }
9805  }
9806  break;
9807 
9809  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
9810  * y <= b/a * z + (d-c)/a, if a < 0
9811  */
9812  assert(var->data.aggregate.var != NULL);
9813  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9814  {
9815  /* a > 0 -> add variable lower bound */
9816  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
9817  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9818  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9819  }
9820  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9821  {
9822  /* a < 0 -> add variable upper bound */
9823  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
9824  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9825  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9826  }
9827  else
9828  {
9829  SCIPerrorMessage("scalar is zero in aggregation\n");
9830  return SCIP_INVALIDDATA;
9831  }
9832  break;
9833 
9835  /* nothing to do here */
9836  break;
9837 
9839  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
9840  assert(var->negatedvar != NULL);
9842  assert(var->negatedvar->negatedvar == var);
9843  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
9844  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
9845  nbdchgs) );
9846  break;
9847 
9848  default:
9849  SCIPerrorMessage("unknown variable status\n");
9850  return SCIP_INVALIDDATA;
9851  }
9852 
9853  return SCIP_OKAY;
9854 }
9855 
9856 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
9857  * if z is binary, the corresponding valid implication for z is also added;
9858  * updates the global bounds of the variable and the vub variable correspondingly
9859  */
9861  SCIP_VAR* var, /**< problem variable */
9862  BMS_BLKMEM* blkmem, /**< block memory */
9863  SCIP_SET* set, /**< global SCIP settings */
9864  SCIP_STAT* stat, /**< problem statistics */
9865  SCIP_PROB* transprob, /**< transformed problem */
9866  SCIP_PROB* origprob, /**< original problem */
9867  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9868  SCIP_LP* lp, /**< current LP data */
9869  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9870  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9871  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9872  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
9873  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
9874  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
9875  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9876  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9877  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9878  )
9879 {
9880  assert(var != NULL);
9881  assert(set != NULL);
9882  assert(var->scip == set->scip);
9883  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
9884  assert(infeasible != NULL);
9885 
9886  SCIPdebugMessage("adding variable upper bound <%s> <= %g<%s> + %g\n",
9887  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9888 
9889  *infeasible = FALSE;
9890  if( nbdchgs != NULL )
9891  *nbdchgs = 0;
9892 
9893  switch( SCIPvarGetStatus(var) )
9894  {
9896  assert(var->data.original.transvar != NULL);
9897  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, lp,
9898  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
9899  break;
9900 
9901  case SCIP_VARSTATUS_COLUMN:
9902  case SCIP_VARSTATUS_LOOSE:
9903  case SCIP_VARSTATUS_FIXED:
9904  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9905  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
9906  SCIPdebugMessage(" -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
9907  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9908 
9909  /* if the vub coefficient is zero, just update the upper bound of the variable */
9910  if( SCIPsetIsZero(set, vubcoef) )
9911  {
9912  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
9913  *infeasible = TRUE;
9914  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
9915  {
9916  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9917  * with the local bound, in this case we need to store the bound change as pending bound change
9918  */
9919  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9920  {
9921  assert(tree != NULL);
9922  assert(transprob != NULL);
9923  assert(SCIPprobIsTransformed(transprob));
9924 
9925  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9926  tree, lp, branchcand, eventqueue, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
9927  }
9928  else
9929  {
9930  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, vubconstant) );
9931  }
9932 
9933  if( nbdchgs != NULL )
9934  (*nbdchgs)++;
9935  }
9936  }
9937  else if( SCIPvarIsActive(vubvar) )
9938  {
9939  SCIP_Real xlb;
9940  SCIP_Real xub;
9941  SCIP_Real zlb;
9942  SCIP_Real zub;
9943  SCIP_Real minvub;
9944  SCIP_Real maxvub;
9945 
9947  assert(vubcoef != 0.0);
9948 
9949  minvub = SCIPsetInfinity(set);
9950  maxvub = SCIPsetInfinity(set);
9951 
9952  xlb = SCIPvarGetLbGlobal(var);
9953  xub = SCIPvarGetUbGlobal(var);
9954  zlb = SCIPvarGetLbGlobal(vubvar);
9955  zub = SCIPvarGetUbGlobal(vubvar);
9956 
9957  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
9958  if( vubcoef >= 0.0 )
9959  {
9960  SCIP_Real newzlb;
9961 
9962  if( !SCIPsetIsInfinity(set, -xlb) )
9963  {
9964  /* x <= b*z + d -> z >= (x-d)/b */
9965  newzlb = (xlb - vubconstant)/vubcoef;
9966  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9967  {
9968  *infeasible = TRUE;
9969  return SCIP_OKAY;
9970  }
9971  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9972  {
9973  /* bound might be adjusted due to integrality condition */
9974  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
9975 
9976  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9977  * with the local bound, in this case we need to store the bound change as pending bound change
9978  */
9979  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9980  {
9981  assert(tree != NULL);
9982  assert(transprob != NULL);
9983  assert(SCIPprobIsTransformed(transprob));
9984 
9985  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9986  tree, lp, branchcand, eventqueue, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9987  }
9988  else
9989  {
9990  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, newzlb) );
9991  }
9992  zlb = newzlb;
9993 
9994  if( nbdchgs != NULL )
9995  (*nbdchgs)++;
9996  }
9997  minvub = vubcoef * zlb + vubconstant;
9998  if( !SCIPsetIsInfinity(set, zub) )
9999  maxvub = vubcoef * zub + vubconstant;
10000  }
10001  else
10002  {
10003  if( !SCIPsetIsInfinity(set, zub) )
10004  maxvub = vubcoef * zub + vubconstant;
10005  if( !SCIPsetIsInfinity(set, -zlb) )
10006  minvub = vubcoef * zlb + vubconstant;
10007  }
10008  }
10009  else
10010  {
10011  SCIP_Real newzub;
10012 
10013  if( !SCIPsetIsInfinity(set, -xlb) )
10014  {
10015  /* x <= b*z + d -> z <= (x-d)/b */
10016  newzub = (xlb - vubconstant)/vubcoef;
10017  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10018  {
10019  *infeasible = TRUE;
10020  return SCIP_OKAY;
10021  }
10022  if( SCIPsetIsFeasLT(set, newzub, zub) )
10023  {
10024  /* bound might be adjusted due to integrality condition */
10025  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10026 
10027  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10028  * with the local bound, in this case we need to store the bound change as pending bound change
10029  */
10030  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10031  {
10032  assert(tree != NULL);
10033  assert(transprob != NULL);
10034  assert(SCIPprobIsTransformed(transprob));
10035 
10036  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10037  tree, lp, branchcand, eventqueue, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10038  }
10039  else
10040  {
10041  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, newzub) );
10042  }
10043  zub = newzub;
10044 
10045  if( nbdchgs != NULL )
10046  (*nbdchgs)++;
10047  }
10048  minvub = vubcoef * zub + vubconstant;
10049  if( !SCIPsetIsInfinity(set, -zlb) )
10050  maxvub = vubcoef * zlb + vubconstant;
10051  }
10052  else
10053  {
10054  if( !SCIPsetIsInfinity(set, zub) )
10055  minvub = vubcoef * zub + vubconstant;
10056  if( !SCIPsetIsInfinity(set, -zlb) )
10057  maxvub = vubcoef * zlb + vubconstant;
10058  }
10059 
10060  }
10061  if( minvub > maxvub )
10062  minvub = maxvub;
10063 
10064  /* adjust bounds due to integrality of vub variable */
10065  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10066  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10067 
10068  /* check bounds for feasibility */
10069  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10070  {
10071  *infeasible = TRUE;
10072  return SCIP_OKAY;
10073  }
10074  /* improve global upper bound of variable */
10075  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10076  {
10077  /* bound might be adjusted due to integrality condition */
10078  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10079 
10080  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10081  * with the local bound, in this case we need to store the bound change as pending bound change
10082  */
10083  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10084  {
10085  assert(tree != NULL);
10086  assert(transprob != NULL);
10087  assert(SCIPprobIsTransformed(transprob));
10088 
10089  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10090  tree, lp, branchcand, eventqueue, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10091  }
10092  else
10093  {
10094  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, maxvub) );
10095  }
10096  xub = maxvub;
10097 
10098  if( nbdchgs != NULL )
10099  (*nbdchgs)++;
10100  }
10101  maxvub = xub;
10102 
10103  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10104  if( SCIPvarIsBinary(vubvar) )
10105  {
10106  /* b > 0: x <= (maxvub - minvub) * z + minvub
10107  * b < 0: x <= (minvub - maxvub) * z + maxvub
10108  */
10109 
10110  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, minvub));
10111 
10112  if( vubcoef >= 0.0 )
10113  {
10114  vubcoef = maxvub - minvub;
10115  vubconstant = minvub;
10116  }
10117  else
10118  {
10119  vubcoef = minvub - maxvub;
10120  vubconstant = maxvub;
10121  }
10122  }
10123 
10124  /* add variable bound to the variable bounds list */
10125  if( SCIPsetIsFeasLT(set, minvub, xub) )
10126  {
10127  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10128  assert(!SCIPsetIsZero(set, vubcoef));
10129 
10130  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10131  * list, thereby also adding the variable bound (or implication) to the other variable
10132  */
10133  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10134  {
10135  /* add corresponding implication:
10136  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10137  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10138  */
10139  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
10140  eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive, infeasible, nbdchgs) );
10141  }
10142  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10143  {
10144  /* add corresponding implication:
10145  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10146  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10147  */
10148  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
10149  eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10150  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10151  }
10152  else
10153  {
10154  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10155  }
10156  }
10157  }
10158  break;
10159 
10161  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10162  * y >= b/a * z + (d-c)/a, if a < 0
10163  */
10164  assert(var->data.aggregate.var != NULL);
10165  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10166  {
10167  /* a > 0 -> add variable upper bound */
10168  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
10169  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10170  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10171  }
10172  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10173  {
10174  /* a < 0 -> add variable lower bound */
10175  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
10176  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10177  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10178  }
10179  else
10180  {
10181  SCIPerrorMessage("scalar is zero in aggregation\n");
10182  return SCIP_INVALIDDATA;
10183  }
10184  break;
10185 
10187  /* nothing to do here */
10188  break;
10189 
10191  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10192  assert(var->negatedvar != NULL);
10194  assert(var->negatedvar->negatedvar == var);
10195  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10196  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10197  nbdchgs) );
10198  break;
10199 
10200  default:
10201  SCIPerrorMessage("unknown variable status\n");
10202  return SCIP_INVALIDDATA;
10203  }
10204 
10205  return SCIP_OKAY;
10206 }
10207 
10208 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10209  * also adds the corresponding implication or variable bound to the implied variable;
10210  * if the implication is conflicting, the variable is fixed to the opposite value;
10211  * if the variable is already fixed to the given value, the implication is performed immediately;
10212  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10213  */
10215  SCIP_VAR* var, /**< problem variable */
10216  BMS_BLKMEM* blkmem, /**< block memory */
10217  SCIP_SET* set, /**< global SCIP settings */
10218  SCIP_STAT* stat, /**< problem statistics */
10219  SCIP_PROB* transprob, /**< transformed problem */
10220  SCIP_PROB* origprob, /**< original problem */
10221  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10222  SCIP_LP* lp, /**< current LP data */
10223  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10224  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10225  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10226  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10227  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10228  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10229  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10230  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10231  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10232  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10233  )
10234 {
10235  assert(var != NULL);
10236  assert(set != NULL);
10237  assert(var->scip == set->scip);
10238  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10239  assert(infeasible != NULL);
10240 
10241  *infeasible = FALSE;
10242  if( nbdchgs != NULL )
10243  *nbdchgs = 0;
10244 
10245  switch( SCIPvarGetStatus(var) )
10246  {
10248  assert(var->data.original.transvar != NULL);
10249  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, lp,
10250  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10251  nbdchgs) );
10252  break;
10253 
10254  case SCIP_VARSTATUS_COLUMN:
10255  case SCIP_VARSTATUS_LOOSE:
10256  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10257  * the variable, the implication can be applied directly;
10258  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10259  */
10260  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10261  {
10262  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10263  {
10264  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
10265  implvar, impltype, implbound, infeasible, nbdchgs) );
10266  }
10267  }
10268  else
10269  {
10270  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10271  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10272  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10273  {
10274  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand,
10275  eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10276  }
10277  }
10278  break;
10279 
10280  case SCIP_VARSTATUS_FIXED:
10281  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10282  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10283  {
10284  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
10285  implvar, impltype, implbound, infeasible, nbdchgs) );
10286  }
10287  break;
10288 
10290  /* implication added for x == 1:
10291  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10292  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10293  * implication added for x == 0:
10294  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10295  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10296  *
10297  * use only binary variables z
10298  */
10299  assert(var->data.aggregate.var != NULL);
10300  if( SCIPvarIsBinary(var->data.aggregate.var) )
10301  {
10302  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10303  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10304 
10305  if( var->data.aggregate.scalar > 0 )
10306  {
10307  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
10308  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10309  nbdchgs) );
10310  }
10311  else
10312  {
10313  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, lp,
10314  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10315  nbdchgs) );
10316  }
10317  }
10318  break;
10319 
10321  /* nothing to do here */
10322  break;
10323 
10325  /* implication added for x == 1:
10326  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10327  * implication added for x == 0:
10328  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10329  */
10330  assert(var->negatedvar != NULL);
10332  assert(var->negatedvar->negatedvar == var);
10333  assert(SCIPvarIsBinary(var->negatedvar));
10334 
10336  {
10337  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10338  branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10339  }
10340  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10341  else
10342  {
10343  /* if the implied variable is of binary type exchange the variables */
10344  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10345  {
10346  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10347  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10348  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10349  infeasible, nbdchgs) );
10350  }
10351  else
10352  {
10353  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10354  * implication as variable bounds
10355  */
10356 
10357  /* add variable lower bound on the negation of var */
10358  if( varfixing )
10359  {
10360  /* (x = 1 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 1), this is done by adding ~x >= b*z + d
10361  * as variable lower bound
10362  */
10363  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10364  branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10365  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10366  }
10367  else
10368  {
10369  /* (x = 0 => i) z = 0 ii) z = 1) <=> ( i) z = 1 ii) z = 0 => ~x = 0), this is done by adding ~x <= b*z + d
10370  * as variable upper bound
10371  */
10372  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10373  branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10374  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10375  }
10376 
10377  /* add variable bound on implvar */
10378  if( impltype == SCIP_BOUNDTYPE_UPPER )
10379  {
10380  /* (z = 1 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 0), this is done by adding z <= b*~x + d
10381  * as variable upper bound
10382  */
10383  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10384  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10385  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10386  }
10387  else
10388  {
10389  /* (z = 0 => i) x = 0 ii) x = 1) <=> ( i) ~x = 0 ii) ~x = 1 => z = 1), this is done by adding z >= b*~x + d
10390  * as variable upper bound
10391  */
10392  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, lp, cliquetable,
10393  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10394  transitive, infeasible, nbdchgs) );
10395  }
10396  }
10397  }
10398  break;
10399 
10400  default:
10401  SCIPerrorMessage("unknown variable status\n");
10402  return SCIP_INVALIDDATA;
10403  }
10404 
10405  return SCIP_OKAY;
10406 }
10407 
10408 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10409  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10410  * both variables must be active, variable x must be binary
10411  */
10413  SCIP_VAR* var, /**< problem variable x */
10414  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10415  SCIP_VAR* implvar, /**< variable y to search for */
10416  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10417  )
10418 {
10419  assert(var != NULL);
10420  assert(implvar != NULL);
10421  assert(SCIPvarIsActive(var));
10422  assert(SCIPvarIsActive(implvar));
10423  assert(SCIPvarIsBinary(var));
10424 
10425  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10426 }
10427 
10428 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10429  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10430  * both variables must be active binary variables
10431  */
10433  SCIP_VAR* var, /**< problem variable x */
10434  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10435  SCIP_VAR* implvar, /**< variable y to search for */
10436  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10437  )
10438 {
10439  assert(SCIPvarIsBinary(implvar));
10440 
10441  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10442 }
10443 
10444 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10446  SCIP_VAR* var, /**< problem variable */
10447  BMS_BLKMEM* blkmem, /**< block memory */
10448  SCIP_SET* set, /**< global SCIP settings */
10449  SCIP_STAT* stat, /**< problem statistics */
10450  SCIP_PROB* transprob, /**< transformed problem */
10451  SCIP_PROB* origprob, /**< original problem */
10452  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10453  SCIP_LP* lp, /**< current LP data */
10454  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10455  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10456  SCIP_Bool value, /**< value to fix variable to */
10457  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10458  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10459  )
10460 {
10461  assert(var != NULL);
10462  assert(set != NULL);
10463  assert(var->scip == set->scip);
10464  assert(infeasible != NULL);
10465 
10466  *infeasible = FALSE;
10467 
10468  if( value == FALSE )
10469  {
10470  if( var->glbdom.lb > 0.5 )
10471  *infeasible = TRUE;
10472  else if( var->glbdom.ub > 0.5 )
10473  {
10474  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10475  * with the local bound, in this case we need to store the bound change as pending bound change
10476  */
10477  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10478  {
10479  assert(tree != NULL);
10480  assert(transprob != NULL);
10481  assert(SCIPprobIsTransformed(transprob));
10482 
10483  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10484  tree, lp, branchcand, eventqueue, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10485  }
10486  else
10487  {
10488  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, 0.0) );
10489  }
10490 
10491  if( nbdchgs != NULL )
10492  (*nbdchgs)++;
10493  }
10494  }
10495  else
10496  {
10497  if( var->glbdom.ub < 0.5 )
10498  *infeasible = TRUE;
10499  else if( var->glbdom.lb < 0.5 )
10500  {
10501  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10502  * with the local bound, in this case we need to store the bound change as pending bound change
10503  */
10504  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10505  {
10506  assert(tree != NULL);
10507  assert(transprob != NULL);
10508  assert(SCIPprobIsTransformed(transprob));
10509 
10510  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10511  tree, lp, branchcand, eventqueue, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10512  }
10513  else
10514  {
10515  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, 1.0) );
10516  }
10517 
10518  if( nbdchgs != NULL )
10519  (*nbdchgs)++;
10520  }
10521  }
10522 
10523  return SCIP_OKAY;
10524 }
10525 
10526 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10527  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10528  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10529  * the opposite of the value they take in the clique
10530  */
10532  SCIP_VAR* var, /**< problem variable */
10533  BMS_BLKMEM* blkmem, /**< block memory */
10534  SCIP_SET* set, /**< global SCIP settings */
10535  SCIP_STAT* stat, /**< problem statistics */
10536  SCIP_PROB* transprob, /**< transformed problem */
10537  SCIP_PROB* origprob, /**< original problem */
10538  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10539  SCIP_LP* lp, /**< current LP data */
10540  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10541  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10542  SCIP_Bool value, /**< value of the variable in the clique */
10543  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10544  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10545  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10546  )
10547 {
10548  assert(var != NULL);
10549  assert(set != NULL);
10550  assert(var->scip == set->scip);
10551  assert(SCIPvarIsBinary(var));
10552  assert(infeasible != NULL);
10553 
10554  *infeasible = FALSE;
10555 
10556  /* get corresponding active problem variable */
10557  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10562  assert(SCIPvarIsBinary(var));
10563 
10564  /* only column and loose variables may be member of a clique */
10566  {
10567  SCIP_Bool doubleentry;
10568  SCIP_Bool oppositeentry;
10569 
10570  /* add variable to clique */
10571  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10572 
10573  /* add clique to variable's clique list */
10574  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10575 
10576  /* check consistency of cliquelist */
10577  SCIPcliquelistCheck(var->cliquelist, var);
10578 
10579  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10580  if( doubleentry )
10581  {
10582  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue, !value,
10583  infeasible, nbdchgs) );
10584  }
10585 
10586  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10587  * to the opposite of the value they take in the clique
10588  */
10589  if( oppositeentry )
10590  {
10591  SCIP_VAR** vars;
10592  SCIP_Bool* values;
10593  int nvars;
10594  int i;
10595 
10596  nvars = SCIPcliqueGetNVars(clique);
10597  vars = SCIPcliqueGetVars(clique);
10598  values = SCIPcliqueGetValues(clique);
10599  for( i = 0; i < nvars && !(*infeasible); ++i )
10600  {
10601  if( vars[i] == var )
10602  continue;
10603 
10604  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, lp, branchcand, eventqueue,
10605  !values[i], infeasible, nbdchgs) );
10606  }
10607  }
10608  }
10609 
10610  return SCIP_OKAY;
10611 }
10612 
10613 /** adds a filled clique to the cliquelists of all corresponding variables */
10615  SCIP_VAR** vars, /**< problem variables */
10616  SCIP_Bool* values, /**< values of the variables in the clique */
10617  int nvars, /**< number of problem variables */
10618  BMS_BLKMEM* blkmem, /**< block memory */
10619  SCIP_SET* set, /**< global SCIP settings */
10620  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10621  )
10622 {
10623  SCIP_VAR* var;
10624  int v;
10625 
10626  assert(vars != NULL);
10627  assert(values != NULL);
10628  assert(nvars > 0);
10629  assert(set != NULL);
10630  assert(blkmem != NULL);
10631  assert(clique != NULL);
10632 
10633  for( v = nvars - 1; v >= 0; --v )
10634  {
10635  var = vars[v];
10636  assert(SCIPvarIsBinary(var));
10638 
10639  /* add clique to variable's clique list */
10640  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10641 
10642  /* check consistency of cliquelist */
10643  SCIPcliquelistCheck(var->cliquelist, var);
10644  }
10645 
10646  return SCIP_OKAY;
10647 }
10648 
10649 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10650  * itself
10651  */
10653  SCIP_VAR* var, /**< problem variable */
10654  BMS_BLKMEM* blkmem, /**< block memory */
10655  SCIP_Bool value, /**< value of the variable in the clique */
10656  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10657  )
10658 {
10659  assert(var != NULL);
10660  assert(SCIPvarIsBinary(var));
10662 
10663  /* delete clique from variable's clique list */
10664  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10665 
10666  return SCIP_OKAY;
10667 }
10668 
10669 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10671  SCIP_VAR* var, /**< problem variable */
10672  BMS_BLKMEM* blkmem, /**< block memory */
10673  SCIP_Bool value, /**< value of the variable in the clique */
10674  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10675  )
10676 {
10677  assert(var != NULL);
10678  assert(SCIPvarIsBinary(var));
10679 
10680  /* get corresponding active problem variable */
10681  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10686  assert(SCIPvarIsBinary(var));
10687 
10688  /* only column and loose variables may be member of a clique */
10690  {
10691  /* delete clique from variable's clique list */
10692  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10693 
10694  /* delete variable from clique */
10695  SCIP_CALL( SCIPcliqueDelVar(clique, var, value) );
10696 
10697  /* check consistency of cliquelist */
10698  SCIPcliquelistCheck(var->cliquelist, var);
10699  }
10700 
10701  return SCIP_OKAY;
10702 }
10703 
10704 /** returns whether there is a clique that contains both given variable/value pairs;
10705  * the variables must be active binary variables;
10706  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10707  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10708  *
10709  * @note a variable with it's negated variable are NOT! in a clique
10710  * @note a variable with itself are in a clique
10711  */
10713  SCIP_VAR* var1, /**< first variable */
10714  SCIP_Bool value1, /**< value of first variable */
10715  SCIP_VAR* var2, /**< second variable */
10716  SCIP_Bool value2, /**< value of second variable */
10717  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10718  )
10719 {
10720  assert(var1 != NULL);
10721  assert(var2 != NULL);
10722  assert(SCIPvarIsActive(var1));
10723  assert(SCIPvarIsActive(var2));
10724  assert(SCIPvarIsBinary(var1));
10725  assert(SCIPvarIsBinary(var2));
10726 
10727  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10728  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10729 }
10730 
10731 /** actually changes the branch factor of the variable and of all parent variables */
10732 static
10734  SCIP_VAR* var, /**< problem variable */
10735  SCIP_SET* set, /**< global SCIP settings */
10736  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10737  )
10738 {
10739  SCIP_VAR* parentvar;
10740  SCIP_Real eps;
10741  int i;
10742 
10743  assert(var != NULL);
10744  assert(set != NULL);
10745  assert(var->scip == set->scip);
10746 
10747  /* only use positive values */
10748  eps = SCIPsetEpsilon(set);
10749  branchfactor = MAX(branchfactor, eps);
10750 
10751  SCIPdebugMessage("process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10752 
10753  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10754  return SCIP_OKAY;
10755 
10756  /* change the branch factor */
10757  var->branchfactor = branchfactor;
10758 
10759  /* process parent variables */
10760  for( i = 0; i < var->nparentvars; ++i )
10761  {
10762  parentvar = var->parentvars[i];
10763  assert(parentvar != NULL);
10764 
10765  switch( SCIPvarGetStatus(parentvar) )
10766  {
10768  /* do not change priorities across the border between transformed and original problem */
10769  break;
10770 
10771  case SCIP_VARSTATUS_COLUMN:
10772  case SCIP_VARSTATUS_LOOSE:
10773  case SCIP_VARSTATUS_FIXED:
10775  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10776  SCIPABORT();
10777  return SCIP_INVALIDDATA; /*lint !e527*/
10778 
10781  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
10782  break;
10783 
10784  default:
10785  SCIPerrorMessage("unknown variable status\n");
10786  SCIPABORT();
10787  return SCIP_ERROR; /*lint !e527*/
10788  }
10789  }
10790 
10791  return SCIP_OKAY;
10792 }
10793 
10794 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
10795  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
10796  */
10798  SCIP_VAR* var, /**< problem variable */
10799  SCIP_SET* set, /**< global SCIP settings */
10800  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10801  )
10802 {
10803  int v;
10804 
10805  assert(var != NULL);
10806  assert(set != NULL);
10807  assert(var->scip == set->scip);
10808  assert(branchfactor >= 0.0);
10809 
10810  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
10811 
10812  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
10813  return SCIP_OKAY;
10814 
10815  /* change priorities of attached variables */
10816  switch( SCIPvarGetStatus(var) )
10817  {
10819  if( var->data.original.transvar != NULL )
10820  {
10821  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
10822  }
10823  else
10824  {
10825  assert(set->stage == SCIP_STAGE_PROBLEM);
10826  var->branchfactor = branchfactor;
10827  }
10828  break;
10829 
10830  case SCIP_VARSTATUS_COLUMN:
10831  case SCIP_VARSTATUS_LOOSE:
10832  case SCIP_VARSTATUS_FIXED:
10833  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
10834  break;
10835 
10837  assert(var->data.aggregate.var != NULL);
10838  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
10839  break;
10840 
10842  assert(!var->donotmultaggr);
10843  for( v = 0; v < var->data.multaggr.nvars; ++v )
10844  {
10845  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
10846  }
10847  break;
10848 
10850  assert(var->negatedvar != NULL);
10852  assert(var->negatedvar->negatedvar == var);
10853  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
10854  break;
10855 
10856  default:
10857  SCIPerrorMessage("unknown variable status\n");
10858  SCIPABORT();
10859  return SCIP_ERROR; /*lint !e527*/
10860  }
10861 
10862  return SCIP_OKAY;
10863 }
10864 
10865 /** actually changes the branch priority of the variable and of all parent variables */
10866 static
10868  SCIP_VAR* var, /**< problem variable */
10869  int branchpriority /**< branching priority of the variable */
10870  )
10871 {
10872  SCIP_VAR* parentvar;
10873  int i;
10874 
10875  assert(var != NULL);
10876 
10877  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
10878  var->name, var->branchpriority, branchpriority);
10879 
10880  if( branchpriority == var->branchpriority )
10881  return SCIP_OKAY;
10882 
10883  /* change the branch priority */
10884  var->branchpriority = branchpriority;
10885 
10886  /* process parent variables */
10887  for( i = 0; i < var->nparentvars; ++i )
10888  {
10889  parentvar = var->parentvars[i];
10890  assert(parentvar != NULL);
10891 
10892  switch( SCIPvarGetStatus(parentvar) )
10893  {
10895  /* do not change priorities across the border between transformed and original problem */
10896  break;
10897 
10898  case SCIP_VARSTATUS_COLUMN:
10899  case SCIP_VARSTATUS_LOOSE:
10900  case SCIP_VARSTATUS_FIXED:
10902  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10903  SCIPABORT();
10904  return SCIP_INVALIDDATA; /*lint !e527*/
10905 
10908  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
10909  break;
10910 
10911  default:
10912  SCIPerrorMessage("unknown variable status\n");
10913  return SCIP_ERROR;
10914  }
10915  }
10916 
10917  return SCIP_OKAY;
10918 }
10919 
10920 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
10921  * with lower priority in selection of branching variable
10922  */
10924  SCIP_VAR* var, /**< problem variable */
10925  int branchpriority /**< branching priority of the variable */
10926  )
10927 {
10928  int v;
10929 
10930  assert(var != NULL);
10931 
10932  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
10933 
10934  if( var->branchpriority == branchpriority )
10935  return SCIP_OKAY;
10936 
10937  /* change priorities of attached variables */
10938  switch( SCIPvarGetStatus(var) )
10939  {
10941  if( var->data.original.transvar != NULL )
10942  {
10943  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
10944  }
10945  else
10946  var->branchpriority = branchpriority;
10947  break;
10948 
10949  case SCIP_VARSTATUS_COLUMN:
10950  case SCIP_VARSTATUS_LOOSE:
10951  case SCIP_VARSTATUS_FIXED:
10952  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
10953  break;
10954 
10956  assert(var->data.aggregate.var != NULL);
10957  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
10958  break;
10959 
10961  assert(!var->donotmultaggr);
10962  for( v = 0; v < var->data.multaggr.nvars; ++v )
10963  {
10964  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
10965  }
10966  break;
10967 
10969  assert(var->negatedvar != NULL);
10971  assert(var->negatedvar->negatedvar == var);
10972  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
10973  break;
10974 
10975  default:
10976  SCIPerrorMessage("unknown variable status\n");
10977  SCIPABORT();
10978  return SCIP_ERROR; /*lint !e527*/
10979  }
10980 
10981  return SCIP_OKAY;
10982 }
10983 
10984 /** actually changes the branch direction of the variable and of all parent variables */
10985 static
10987  SCIP_VAR* var, /**< problem variable */
10988  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
10989  )
10990 {
10991  SCIP_VAR* parentvar;
10992  int i;
10993 
10994  assert(var != NULL);
10995 
10996  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
10997  var->name, var->branchdirection, branchdirection);
10998 
10999  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11000  return SCIP_OKAY;
11001 
11002  /* change the branch direction */
11003  var->branchdirection = branchdirection; /*lint !e641*/
11004 
11005  /* process parent variables */
11006  for( i = 0; i < var->nparentvars; ++i )
11007  {
11008  parentvar = var->parentvars[i];
11009  assert(parentvar != NULL);
11010 
11011  switch( SCIPvarGetStatus(parentvar) )
11012  {
11014  /* do not change directions across the border between transformed and original problem */
11015  break;
11016 
11017  case SCIP_VARSTATUS_COLUMN:
11018  case SCIP_VARSTATUS_LOOSE:
11019  case SCIP_VARSTATUS_FIXED:
11021  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11022  SCIPABORT();
11023  return SCIP_INVALIDDATA; /*lint !e527*/
11024 
11026  if( parentvar->data.aggregate.scalar > 0.0 )
11027  {
11028  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11029  }
11030  else
11031  {
11032  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11033  }
11034  break;
11035 
11037  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11038  break;
11039 
11040  default:
11041  SCIPerrorMessage("unknown variable status\n");
11042  SCIPABORT();
11043  return SCIP_ERROR; /*lint !e527*/
11044  }
11045  }
11046 
11047  return SCIP_OKAY;
11048 }
11049 
11050 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11051  * with lower direction in selection of branching variable
11052  */
11054  SCIP_VAR* var, /**< problem variable */
11055  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11056  )
11057 {
11058  int v;
11059 
11060  assert(var != NULL);
11061 
11062  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11063 
11064  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11065  return SCIP_OKAY;
11066 
11067  /* change directions of attached variables */
11068  switch( SCIPvarGetStatus(var) )
11069  {
11071  if( var->data.original.transvar != NULL )
11072  {
11073  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11074  }
11075  else
11076  var->branchdirection = branchdirection; /*lint !e641*/
11077  break;
11078 
11079  case SCIP_VARSTATUS_COLUMN:
11080  case SCIP_VARSTATUS_LOOSE:
11081  case SCIP_VARSTATUS_FIXED:
11082  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11083  break;
11084 
11086  assert(var->data.aggregate.var != NULL);
11087  if( var->data.aggregate.scalar > 0.0 )
11088  {
11089  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11090  }
11091  else
11092  {
11094  }
11095  break;
11096 
11098  assert(!var->donotmultaggr);
11099  for( v = 0; v < var->data.multaggr.nvars; ++v )
11100  {
11101  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11102  assert(var->data.multaggr.vars[v] != NULL);
11104  {
11105  if( var->data.multaggr.scalars[v] > 0.0 )
11106  {
11107  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11108  }
11109  else
11110  {
11112  }
11113  }
11114  }
11115  break;
11116 
11118  assert(var->negatedvar != NULL);
11120  assert(var->negatedvar->negatedvar == var);
11122  break;
11123 
11124  default:
11125  SCIPerrorMessage("unknown variable status\n");
11126  SCIPABORT();
11127  return SCIP_ERROR; /*lint !e527*/
11128  }
11129 
11130  return SCIP_OKAY;
11131 }
11132 
11133 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11134  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11135  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11136  * are equal, which means both variables are equal
11137  */
11139  SCIP_VAR* var1, /**< first problem variable */
11140  SCIP_VAR* var2 /**< second problem variable */
11141  )
11142 {
11143  assert(var1 != NULL);
11144  assert(var2 != NULL);
11147 
11149  var1 = SCIPvarGetNegatedVar(var1);
11151  var2 = SCIPvarGetNegatedVar(var2);
11152 
11153  assert(var1 != NULL);
11154  assert(var2 != NULL);
11155 
11156  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11157  return -1;
11158  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11159  return +1;
11160 
11161  assert(var1 == var2);
11162  return 0;
11163 }
11164 
11165 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11166  * variables are handled as the same variables
11167  */
11168 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11170  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11171 }
11172 
11173 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11174  * variable index; returns 0 if both indices are equal, which means both variables are equal
11175  */
11176 int SCIPvarCompare(
11177  SCIP_VAR* var1, /**< first problem variable */
11178  SCIP_VAR* var2 /**< second problem variable */
11179  )
11180 {
11181  assert(var1 != NULL);
11182  assert(var2 != NULL);
11183 
11184  if( var1->index < var2->index )
11185  return -1;
11186  else if( var1->index > var2->index )
11187  return +1;
11188  else
11189  {
11190  assert(var1 == var2);
11191  return 0;
11192  }
11193 }
11194 
11195 /** comparison method for sorting variables by non-decreasing index */
11196 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11198  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11199 }
11200 
11201 /** comparison method for sorting variables by non-decreasing objective coefficient */
11202 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11204  SCIP_Real obj1;
11205  SCIP_Real obj2;
11206 
11207  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11208  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11209 
11210  if( obj1 < obj2 )
11211  return -1;
11212  else if( obj1 > obj2 )
11213  return +1;
11214  else
11215  return 0;
11216 }
11217 
11218 /** hash key retrieval function for variables */
11219 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11220 { /*lint --e{715}*/
11221  return elem;
11222 }
11223 
11224 /** returns TRUE iff the indices of both variables are equal */
11225 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11226 { /*lint --e{715}*/
11227  if( key1 == key2 )
11228  return TRUE;
11229  return FALSE;
11230 }
11231 
11232 /** returns the hash value of the key */
11233 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11234 { /*lint --e{715}*/
11235  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11236  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11237 }
11238 
11239 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11241  SCIP_SET* set, /**< global SCIP settings */
11242  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11243  * variables, if enough slots exist
11244  */
11245  int* nvars, /**< number of given variables, and as output number of active variables,
11246  * if enough slots exist
11247  */
11248  int varssize, /**< available slots in vars array */
11249  int* requiredsize /**< pointer to store the required array size for the active variables */
11250  )
11251 {
11252  SCIP_VAR** activevars;
11253  int nactivevars;
11254  int activevarssize;
11255 
11256  SCIP_VAR* var;
11257  int v;
11258 
11259  SCIP_VAR** tmpvars;
11260  SCIP_VAR** multvars;
11261  int tmpvarssize;
11262  int ntmpvars;
11263  int noldtmpvars;
11264  int nmultvars;
11265 
11266  assert(set != NULL);
11267  assert(nvars != NULL);
11268  assert(vars != NULL || *nvars == 0);
11269  assert(varssize >= *nvars);
11270  assert(requiredsize != NULL);
11271 
11272  *requiredsize = 0;
11273 
11274  if( *nvars == 0 )
11275  return SCIP_OKAY;
11276 
11277  nactivevars = 0;
11278  activevarssize = *nvars;
11279  ntmpvars = *nvars;
11280  tmpvarssize = *nvars;
11281 
11282  /* temporary memory */
11283  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11284  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11285 
11286  noldtmpvars = ntmpvars;
11287 
11288  /* sort all variables to combine equal variables easily */
11289  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11290  for( v = ntmpvars - 1; v > 0; --v )
11291  {
11292  /* combine same variables */
11293  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11294  {
11295  --ntmpvars;
11296  tmpvars[v] = tmpvars[ntmpvars];
11297  }
11298  }
11299  /* sort all variables again to combine equal variables later on */
11300  if( noldtmpvars > ntmpvars )
11301  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11302 
11303  /* collect for each variable the representation in active variables */
11304  while( ntmpvars >= 1 )
11305  {
11306  --ntmpvars;
11307  var = tmpvars[ntmpvars];
11308  assert( var != NULL );
11309 
11310  switch( SCIPvarGetStatus(var) )
11311  {
11313  if( var->data.original.transvar == NULL )
11314  {
11315  SCIPerrorMessage("original variable has no transformed variable attached\n");
11316  SCIPABORT();
11317  return SCIP_INVALIDDATA; /*lint !e527*/
11318  }
11319  tmpvars[ntmpvars] = var->data.original.transvar;
11320  ++ntmpvars;
11321  break;
11322 
11324  tmpvars[ntmpvars] = var->data.aggregate.var;
11325  ++ntmpvars;
11326  break;
11327 
11329  tmpvars[ntmpvars] = var->negatedvar;
11330  ++ntmpvars;
11331  break;
11332 
11333  case SCIP_VARSTATUS_LOOSE:
11334  case SCIP_VARSTATUS_COLUMN:
11335  /* check for space in temporary memory */
11336  if( nactivevars >= activevarssize )
11337  {
11338  activevarssize *= 2;
11339  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11340  assert(nactivevars < activevarssize);
11341  }
11342  activevars[nactivevars] = var;
11343  nactivevars++;
11344  break;
11345 
11347  /* x = a_1*y_1 + ... + a_n*y_n + c */
11348  nmultvars = var->data.multaggr.nvars;
11349  multvars = var->data.multaggr.vars;
11350 
11351  /* check for space in temporary memory */
11352  if( nmultvars + ntmpvars > tmpvarssize )
11353  {
11354  while( nmultvars + ntmpvars > tmpvarssize )
11355  tmpvarssize *= 2;
11356  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11357  assert(nmultvars + ntmpvars <= tmpvarssize);
11358  }
11359 
11360  /* copy all multi-aggregation variables into our working array */
11361  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11362 
11363  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11364  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11365 
11366  ntmpvars += nmultvars;
11367  noldtmpvars = ntmpvars;
11368 
11369  /* sort all variables to combine equal variables easily */
11370  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11371  for( v = ntmpvars - 1; v > 0; --v )
11372  {
11373  /* combine same variables */
11374  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11375  {
11376  --ntmpvars;
11377  tmpvars[v] = tmpvars[ntmpvars];
11378  }
11379  }
11380  /* sort all variables again to combine equal variables later on */
11381  if( noldtmpvars > ntmpvars )
11382  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11383 
11384  break;
11385 
11386  case SCIP_VARSTATUS_FIXED:
11387  /* no need for memorizing fixed variables */
11388  break;
11389 
11390  default:
11391  SCIPerrorMessage("unknown variable status\n");
11392  SCIPABORT();
11393  return SCIP_INVALIDDATA; /*lint !e527*/
11394  }
11395  }
11396 
11397  /* sort variable array by variable index */
11398  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11399 
11400  /* eliminate duplicates and count required size */
11401  v = nactivevars - 1;
11402  while( v > 0 )
11403  {
11404  /* combine both variable since they are the same */
11405  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11406  {
11407  --nactivevars;
11408  activevars[v] = activevars[nactivevars];
11409  }
11410  --v;
11411  }
11412  *requiredsize = nactivevars;
11413 
11414  if( varssize >= *requiredsize )
11415  {
11416  assert(vars != NULL);
11417 
11418  *nvars = *requiredsize;
11419  BMScopyMemoryArray(vars, activevars, nactivevars);
11420  }
11421 
11422  SCIPsetFreeBufferArray(set, &tmpvars);
11423  SCIPsetFreeBufferArray(set, &activevars);
11424 
11425  return SCIP_OKAY;
11426 }
11427 
11428 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11429  * @note the content of the given array will/might change
11430  */
11431 void SCIPvarsGetProbvar(
11432  SCIP_VAR** vars, /**< array of problem variables */
11433  int nvars /**< number of variables */
11434  )
11435 {
11436  int v;
11437 
11438  assert(vars != NULL || nvars == 0);
11439 
11440  for( v = nvars - 1; v >= 0; --v )
11441  {
11442  assert(vars != NULL);
11443  assert(vars[v] != NULL);
11444 
11445  vars[v] = SCIPvarGetProbvar(vars[v]);
11446  assert(vars[v] != NULL);
11447  }
11448 }
11449 
11450 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11452  SCIP_VAR* var /**< problem variable */
11453  )
11454 {
11455  SCIP_VAR* retvar;
11456 
11457  assert(var != NULL);
11458 
11459  retvar = var;
11460 
11461  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11462 
11463  while( TRUE ) /*lint !e716 */
11464  {
11465  assert(retvar != NULL);
11466 
11467  switch( SCIPvarGetStatus(retvar) )
11468  {
11470  if( retvar->data.original.transvar == NULL )
11471  {
11472  SCIPerrorMessage("original variable has no transformed variable attached\n");
11473  SCIPABORT();
11474  return NULL; /*lint !e527 */
11475  }
11476  retvar = retvar->data.original.transvar;
11477  break;
11478 
11479  case SCIP_VARSTATUS_LOOSE:
11480  case SCIP_VARSTATUS_COLUMN:
11481  case SCIP_VARSTATUS_FIXED:
11482  return retvar;
11483 
11485  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11486  if ( retvar->data.multaggr.nvars == 1 )
11487  retvar = retvar->data.multaggr.vars[0];
11488  else
11489  return retvar;
11490  break;
11491 
11493  retvar = retvar->data.aggregate.var;
11494  break;
11495 
11497  retvar = retvar->negatedvar;
11498  break;
11499 
11500  default:
11501  SCIPerrorMessage("unknown variable status\n");
11502  SCIPABORT();
11503  return NULL; /*lint !e527*/
11504  }
11505  }
11506 }
11507 
11508 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11509  * negation status of each variable
11510  */
11512  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11513  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11514  int nvars /**< number of variables and values in vars and negated array */
11515  )
11516 {
11517  SCIP_VAR** var;
11518  SCIP_Bool* negated;
11519  int v;
11520 
11521  assert(vars != NULL);
11522  assert(*vars != NULL || nvars == 0);
11523  assert(negatedarr != NULL);
11524  assert(*negatedarr != NULL || nvars == 0);
11525 
11526  for( v = nvars - 1; v >= 0; --v )
11527  {
11528  var = &((*vars)[v]);
11529  negated = &((*negatedarr)[v]);
11530 
11531  /* get problem variable */
11532  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11533  }
11534 
11535  return SCIP_OKAY;
11536 }
11537 
11538 
11539 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11540  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11541  * FALSE is used)
11542  */
11544  SCIP_VAR** var, /**< pointer to binary problem variable */
11545  SCIP_Bool* negated /**< pointer to update the negation status */
11546  )
11547 {
11548  assert(var != NULL);
11549  assert(*var != NULL);
11550  assert(negated != NULL);
11551 
11552  while( *var != NULL )
11553  {
11554  assert(SCIPvarIsBinary(*var));
11555 
11556  switch( SCIPvarGetStatus(*var) )
11557  {
11559  if( (*var)->data.original.transvar == NULL )
11560  return SCIP_OKAY;
11561  *var = (*var)->data.original.transvar;
11562  break;
11563 
11564  case SCIP_VARSTATUS_LOOSE:
11565  case SCIP_VARSTATUS_COLUMN:
11566  case SCIP_VARSTATUS_FIXED:
11567  return SCIP_OKAY;
11568 
11570  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11571  if ( (*var)->data.multaggr.nvars == 1 )
11572  {
11573  assert( (*var)->data.multaggr.vars != NULL );
11574  assert( (*var)->data.multaggr.scalars != NULL );
11575  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11576  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11577 
11578  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11579  * another variable which needs to be fixed
11580  *
11581  * e.g. x = y - 1 => (x = 0 && y = 1)
11582  * e.g. x = y + 1 => (x = 1 && y = 0)
11583  *
11584  * is this special case we need to return the muti-aggregation
11585  */
11586  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)) )
11587  {
11588  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11589  }
11590  else
11591  {
11592  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11593  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11594  * fixed to zero, but should be done by another enforcement; so not depending on the scalar, we
11595  * will return the aggregation variable
11596  */
11597  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11598  return SCIP_OKAY;
11599 
11600  assert( EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) );
11601  assert( EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11602 
11603  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11604  {
11605  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11606  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11607  * variable itself is multi-aggregated again?
11608  */
11609  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11610  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11611  SCIPvarGetNLocksUp((*var)->data.multaggr.vars[0]) > 0) : TRUE);
11612  }
11613  else
11614  {
11615  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11616 
11617  *negated = !(*negated);
11618  }
11619  *var = (*var)->data.multaggr.vars[0];
11620  break;
11621  }
11622  }
11623  return SCIP_OKAY;
11624 
11625  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11626  assert((*var)->data.aggregate.var != NULL);
11627  assert(SCIPvarIsBinary((*var)->data.aggregate.var));
11628  assert(EPSZ((*var)->data.aggregate.constant, 1e-06) || EPSEQ((*var)->data.aggregate.constant, 1.0, 1e-06));
11629  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11630  assert(EPSZ((*var)->data.aggregate.constant, 1e-06) == EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06));
11631 
11632  *negated = (*negated != ((*var)->data.aggregate.scalar < 0.0));
11633  *var = (*var)->data.aggregate.var;
11634  break;
11635 
11636  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11637  assert((*var)->negatedvar != NULL);
11638 
11639  *negated = !(*negated);
11640  *var = (*var)->negatedvar;
11641  break;
11642 
11643  default:
11644  SCIPerrorMessage("unknown variable status\n");
11645  return SCIP_INVALIDDATA;
11646  }
11647  }
11648 
11649  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11650  return SCIP_INVALIDDATA;
11651 }
11652 
11653 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11654  * values
11655  */
11657  SCIP_VAR** var, /**< pointer to problem variable */
11658  SCIP_Real* bound, /**< pointer to bound value to transform */
11659  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11660  )
11661 {
11662  assert(var != NULL);
11663  assert(*var != NULL);
11664  assert(bound != NULL);
11665  assert(boundtype != NULL);
11666 
11667  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11668 
11669  switch( SCIPvarGetStatus(*var) )
11670  {
11672  if( (*var)->data.original.transvar == NULL )
11673  {
11674  SCIPerrorMessage("original variable has no transformed variable attached\n");
11675  return SCIP_INVALIDDATA;
11676  }
11677  *var = (*var)->data.original.transvar;
11678  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11679  break;
11680 
11681  case SCIP_VARSTATUS_LOOSE:
11682  case SCIP_VARSTATUS_COLUMN:
11683  case SCIP_VARSTATUS_FIXED:
11684  break;
11685 
11687  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11688  if ( (*var)->data.multaggr.nvars == 1 )
11689  {
11690  assert( (*var)->data.multaggr.vars != NULL );
11691  assert( (*var)->data.multaggr.scalars != NULL );
11692  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11693 
11694  (*bound) /= (*var)->data.multaggr.scalars[0];
11695  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11696  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11697  {
11698  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11699  *boundtype = SCIP_BOUNDTYPE_UPPER;
11700  else
11701  *boundtype = SCIP_BOUNDTYPE_LOWER;
11702  }
11703  *var = (*var)->data.multaggr.vars[0];
11704  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11705  }
11706  break;
11707 
11708  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11709  assert((*var)->data.aggregate.var != NULL);
11710  assert((*var)->data.aggregate.scalar != 0.0);
11711 
11712  (*bound) /= (*var)->data.aggregate.scalar;
11713  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11714  if( (*var)->data.aggregate.scalar < 0.0 )
11715  {
11716  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11717  *boundtype = SCIP_BOUNDTYPE_UPPER;
11718  else
11719  *boundtype = SCIP_BOUNDTYPE_LOWER;
11720  }
11721  *var = (*var)->data.aggregate.var;
11722  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11723  break;
11724 
11725  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11726  assert((*var)->negatedvar != NULL);
11727  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11728  assert((*var)->negatedvar->negatedvar == *var);
11729  (*bound) = (*var)->data.negate.constant - *bound;
11730  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11731  *boundtype = SCIP_BOUNDTYPE_UPPER;
11732  else
11733  *boundtype = SCIP_BOUNDTYPE_LOWER;
11734  *var = (*var)->negatedvar;
11735  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11736  break;
11737 
11738  default:
11739  SCIPerrorMessage("unknown variable status\n");
11740  return SCIP_INVALIDDATA;
11741  }
11742 
11743  return SCIP_OKAY;
11744 }
11745 
11746 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
11747  * values
11748  */
11750  SCIP_VAR** var, /**< pointer to problem variable */
11751  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
11752  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
11753  )
11754 {
11755  assert(var != NULL);
11756  assert(*var != NULL);
11757  assert(left != NULL);
11758  assert(right != NULL);
11759 
11760  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
11761 
11762  switch( SCIPvarGetStatus(*var) )
11763  {
11765  if( (*var)->data.original.transvar == NULL )
11766  {
11767  SCIPerrorMessage("original variable has no transformed variable attached\n");
11768  return SCIP_INVALIDDATA;
11769  }
11770  *var = (*var)->data.original.transvar;
11771  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11772  break;
11773 
11774  case SCIP_VARSTATUS_LOOSE:
11775  case SCIP_VARSTATUS_COLUMN:
11776  case SCIP_VARSTATUS_FIXED:
11778  break;
11779 
11780  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11781  assert((*var)->data.aggregate.var != NULL);
11782  assert((*var)->data.aggregate.scalar != 0.0);
11783 
11784  /* scale back */
11785  (*left) /= (*var)->data.aggregate.scalar;
11786  (*right) /= (*var)->data.aggregate.scalar;
11787 
11788  /* shift back */
11789  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11790  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11791 
11792  *var = (*var)->data.aggregate.var;
11793 
11794  /* check if the interval bounds have to swapped */
11795  if( (*var)->data.aggregate.scalar < 0.0 )
11796  {
11797  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11798  }
11799  else
11800  {
11801  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11802  }
11803  break;
11804 
11805  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11806  assert((*var)->negatedvar != NULL);
11807  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11808  assert((*var)->negatedvar->negatedvar == *var);
11809 
11810  /* shift and scale back */
11811  (*left) = (*var)->data.negate.constant - (*left);
11812  (*right) = (*var)->data.negate.constant - (*right);
11813 
11814  *var = (*var)->negatedvar;
11815 
11816  /* through the negated variable the left and right interval bound have to swapped */
11817  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11818  break;
11819 
11820  default:
11821  SCIPerrorMessage("unknown variable status\n");
11822  return SCIP_INVALIDDATA;
11823  }
11824 
11825  return SCIP_OKAY;
11826 }
11827 
11828 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
11829  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
11830  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
11831  * with only one active variable (this can happen due to fixings after the multi-aggregation),
11832  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
11833  */
11835  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
11836  SCIP_SET* set, /**< global SCIP settings */
11837  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
11838  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
11839  )
11840 {
11841  assert(var != NULL);
11842  assert(scalar != NULL);
11843  assert(constant != NULL);
11844 
11845  while( *var != NULL )
11846  {
11847  switch( SCIPvarGetStatus(*var) )
11848  {
11850  if( (*var)->data.original.transvar == NULL )
11851  {
11852  SCIPerrorMessage("original variable has no transformed variable attached\n");
11853  return SCIP_INVALIDDATA;
11854  }
11855  *var = (*var)->data.original.transvar;
11856  break;
11857 
11858  case SCIP_VARSTATUS_LOOSE:
11859  case SCIP_VARSTATUS_COLUMN:
11860  return SCIP_OKAY;
11861 
11862  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
11863  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11864  {
11865  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
11866  {
11867  assert(*scalar != 0.0);
11868  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
11869  (*constant) = SCIPsetInfinity(set);
11870  else
11871  (*constant) = -SCIPsetInfinity(set);
11872  }
11873  else
11874  (*constant) += *scalar * (*var)->glbdom.lb;
11875  }
11876 #ifndef NDEBUG
11877  else
11878  {
11879  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
11880  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11881  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
11882  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11883  }
11884 #endif
11885  *scalar = 0.0;
11886  return SCIP_OKAY;
11887 
11889  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11890  if ( (*var)->data.multaggr.nvars == 1 )
11891  {
11892  assert((*var)->data.multaggr.vars != NULL);
11893  assert((*var)->data.multaggr.scalars != NULL);
11894  assert((*var)->data.multaggr.vars[0] != NULL);
11895  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11896  {
11897  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
11898  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
11899  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
11900  */
11901  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
11902  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
11903  {
11904  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
11905  {
11906  assert(!SCIPsetIsInfinity(set, -(*constant)));
11907  (*constant) = SCIPsetInfinity(set);
11908  }
11909  else
11910  {
11911  assert(!SCIPsetIsInfinity(set, *constant));
11912  (*constant) = -SCIPsetInfinity(set);
11913  }
11914  (*scalar) = 0.0;
11915  }
11916  else
11917  (*constant) += *scalar * (*var)->data.multaggr.constant;
11918  }
11919  (*scalar) *= (*var)->data.multaggr.scalars[0];
11920  *var = (*var)->data.multaggr.vars[0];
11921  break;
11922  }
11923  return SCIP_OKAY;
11924 
11925  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11926  assert((*var)->data.aggregate.var != NULL);
11927  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
11928  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
11929  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11930  (*constant) += *scalar * (*var)->data.aggregate.constant;
11931  (*scalar) *= (*var)->data.aggregate.scalar;
11932  *var = (*var)->data.aggregate.var;
11933  break;
11934 
11935  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11936  assert((*var)->negatedvar != NULL);
11937  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11938  assert((*var)->negatedvar->negatedvar == *var);
11939  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
11940  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
11941  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11942  (*constant) += *scalar * (*var)->data.negate.constant;
11943  (*scalar) *= -1.0;
11944  *var = (*var)->negatedvar;
11945  break;
11946 
11947  default:
11948  SCIPerrorMessage("unknown variable status\n");
11949  SCIPABORT();
11950  return SCIP_INVALIDDATA; /*lint !e527*/
11951  }
11952  }
11953  *scalar = 0.0;
11954 
11955  return SCIP_OKAY;
11956 }
11957 
11958 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
11959  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
11960  */
11962  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
11963  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
11964  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
11965  )
11966 {
11967  SCIP_VAR* parentvar;
11968 
11969  assert(var != NULL);
11970  assert(*var != NULL);
11971  assert(scalar != NULL);
11972  assert(constant != NULL);
11973 
11974  while( !SCIPvarIsOriginal(*var) )
11975  {
11976  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
11977  * var
11978  */
11979  if( (*var)->nparentvars == 0 )
11980  {
11981  /* negated variables do not need to have a parent variables, and negated variables can exist in original
11982  * space
11983  */
11985  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
11986  {
11987  *scalar *= -1.0;
11988  *constant -= (*var)->data.negate.constant * (*scalar);
11989  *var = (*var)->negatedvar;
11990 
11991  continue;
11992  }
11993  /* if the variables does not have any parent the variables was created during solving and has no original
11994  * counterpart
11995  */
11996  else
11997  {
11998  *var = NULL;
11999 
12000  return SCIP_OKAY;
12001  }
12002  }
12003 
12004  /* follow the link to the first parent variable */
12005  parentvar = (*var)->parentvars[0];
12006  assert(parentvar != NULL);
12007 
12008  switch( SCIPvarGetStatus(parentvar) )
12009  {
12011  break;
12012 
12013  case SCIP_VARSTATUS_COLUMN:
12014  case SCIP_VARSTATUS_LOOSE:
12015  case SCIP_VARSTATUS_FIXED:
12017  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12018  return SCIP_INVALIDDATA;
12019 
12020  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12021  assert(parentvar->data.aggregate.var == *var);
12022  assert(parentvar->data.aggregate.scalar != 0.0);
12023  *scalar /= parentvar->data.aggregate.scalar;
12024  *constant -= parentvar->data.aggregate.constant * (*scalar);
12025  break;
12026 
12027  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12028  assert(parentvar->negatedvar != NULL);
12029  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12030  assert(parentvar->negatedvar->negatedvar == parentvar);
12031  *scalar *= -1.0;
12032  *constant -= parentvar->data.negate.constant * (*scalar);
12033  break;
12034 
12035  default:
12036  SCIPerrorMessage("unknown variable status\n");
12037  return SCIP_INVALIDDATA;
12038  }
12039 
12040  assert( parentvar != NULL );
12041  *var = parentvar;
12042  }
12043 
12044  return SCIP_OKAY;
12045 }
12046 
12047 /** returns whether the given variable is the direct counterpart of an original problem variable */
12049  SCIP_VAR* var /**< problem variable */
12050  )
12051 {
12052  SCIP_VAR* parentvar;
12053  assert(var != NULL);
12054 
12055  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12056  return FALSE;
12057 
12058  assert(var->parentvars != NULL);
12059  parentvar = var->parentvars[0];
12060  assert(parentvar != NULL);
12061 
12062  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12063  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12064  parentvar = parentvar->parentvars[0];
12065  assert( parentvar != NULL );
12066 
12067  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12068 }
12069 
12070 /** gets objective value of variable in current SCIP_LP; the value can be different from the bound stored in the variable's own
12071  * data due to diving, that operate only on the LP without updating the variables
12072  */
12074  SCIP_VAR* var /**< problem variable */
12075  )
12076 {
12077  assert(var != NULL);
12078 
12079  /* get bounds of attached variables */
12080  switch( SCIPvarGetStatus(var) )
12081  {
12083  assert(var->data.original.transvar != NULL);
12084  return SCIPvarGetObjLP(var->data.original.transvar);
12085 
12086  case SCIP_VARSTATUS_COLUMN:
12087  assert(var->data.col != NULL);
12088  return SCIPcolGetObj(var->data.col);
12089 
12090  case SCIP_VARSTATUS_LOOSE:
12091  case SCIP_VARSTATUS_FIXED:
12092  return var->obj;
12093 
12094  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12095  assert(var->data.aggregate.var != NULL);
12096  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12097 
12099  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12100  SCIPABORT();
12101  return 0.0; /*lint !e527*/
12102 
12103  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12104  assert(var->negatedvar != NULL);
12106  assert(var->negatedvar->negatedvar == var);
12107  return -SCIPvarGetObjLP(var->negatedvar);
12108 
12109  default:
12110  SCIPerrorMessage("unknown variable status\n");
12111  SCIPABORT();
12112  return 0.0; /*lint !e527*/
12113  }
12114 }
12115 
12116 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12117  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12118  */
12120  SCIP_VAR* var, /**< problem variable */
12121  SCIP_SET* set /**< global SCIP settings */
12122  )
12123 {
12124  assert(var != NULL);
12125  assert(set != NULL);
12126  assert(var->scip == set->scip);
12127 
12128  /* get bounds of attached variables */
12129  switch( SCIPvarGetStatus(var) )
12130  {
12132  assert(var->data.original.transvar != NULL);
12133  return SCIPvarGetLbLP(var->data.original.transvar, set);
12134 
12135  case SCIP_VARSTATUS_COLUMN:
12136  assert(var->data.col != NULL);
12137  return SCIPcolGetLb(var->data.col);
12138 
12139  case SCIP_VARSTATUS_LOOSE:
12140  case SCIP_VARSTATUS_FIXED:
12141  return var->locdom.lb;
12142 
12143  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12144  assert(var->data.aggregate.var != NULL);
12145  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12146  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12147  {
12148  return -SCIPsetInfinity(set);
12149  }
12150  else if( var->data.aggregate.scalar > 0.0 )
12151  {
12152  /* a > 0 -> get lower bound of y */
12153  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12154  }
12155  else if( var->data.aggregate.scalar < 0.0 )
12156  {
12157  /* a < 0 -> get upper bound of y */
12158  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12159  }
12160  else
12161  {
12162  SCIPerrorMessage("scalar is zero in aggregation\n");
12163  SCIPABORT();
12164  return SCIP_INVALID; /*lint !e527*/
12165  }
12166 
12168  /**@todo get the sides of the corresponding linear constraint */
12169  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12170  SCIPABORT();
12171  return SCIP_INVALID; /*lint !e527*/
12172 
12173  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12174  assert(var->negatedvar != NULL);
12176  assert(var->negatedvar->negatedvar == var);
12177  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12178 
12179  default:
12180  SCIPerrorMessage("unknown variable status\n");
12181  SCIPABORT();
12182  return SCIP_INVALID; /*lint !e527*/
12183  }
12184 }
12185 
12186 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12187  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12188  */
12190  SCIP_VAR* var, /**< problem variable */
12191  SCIP_SET* set /**< global SCIP settings */
12192  )
12193 {
12194  assert(var != NULL);
12195  assert(set != NULL);
12196  assert(var->scip == set->scip);
12197 
12198  /* get bounds of attached variables */
12199  switch( SCIPvarGetStatus(var) )
12200  {
12202  assert(var->data.original.transvar != NULL);
12203  return SCIPvarGetUbLP(var->data.original.transvar, set);
12204 
12205  case SCIP_VARSTATUS_COLUMN:
12206  assert(var->data.col != NULL);
12207  return SCIPcolGetUb(var->data.col);
12208 
12209  case SCIP_VARSTATUS_LOOSE:
12210  case SCIP_VARSTATUS_FIXED:
12211  return var->locdom.ub;
12212 
12213  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12214  assert(var->data.aggregate.var != NULL);
12215  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12216  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12217  {
12218  return SCIPsetInfinity(set);
12219  }
12220  if( var->data.aggregate.scalar > 0.0 )
12221  {
12222  /* a > 0 -> get upper bound of y */
12223  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12224  }
12225  else if( var->data.aggregate.scalar < 0.0 )
12226  {
12227  /* a < 0 -> get lower bound of y */
12228  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12229  }
12230  else
12231  {
12232  SCIPerrorMessage("scalar is zero in aggregation\n");
12233  SCIPABORT();
12234  return SCIP_INVALID; /*lint !e527*/
12235  }
12236 
12238  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12239  SCIPABORT();
12240  return SCIP_INVALID; /*lint !e527*/
12241 
12242  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12243  assert(var->negatedvar != NULL);
12245  assert(var->negatedvar->negatedvar == var);
12246  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12247 
12248  default:
12249  SCIPerrorMessage("unknown variable status\n");
12250  SCIPABORT();
12251  return SCIP_INVALID; /*lint !e527*/
12252  }
12253 }
12254 
12255 /** gets primal LP solution value of variable */
12257  SCIP_VAR* var /**< problem variable */
12258  )
12259 {
12260  assert(var != NULL);
12261 
12262  switch( SCIPvarGetStatus(var) )
12263  {
12265  if( var->data.original.transvar == NULL )
12266  return SCIP_INVALID;
12267  return SCIPvarGetLPSol(var->data.original.transvar);
12268 
12269  case SCIP_VARSTATUS_LOOSE:
12270  return SCIPvarGetBestBoundLocal(var);
12271 
12272  case SCIP_VARSTATUS_COLUMN:
12273  assert(var->data.col != NULL);
12274  return SCIPcolGetPrimsol(var->data.col);
12275 
12276  case SCIP_VARSTATUS_FIXED:
12277  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12278  return var->locdom.lb;
12279 
12281  {
12282  SCIP_Real lpsolval;
12283 
12284  assert(var->data.aggregate.var != NULL);
12285  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12286 
12287  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12288  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12289  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12290  * (or is called by) a public interface method; instead, we only assert that values are finite
12291  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12292  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12293  */
12294  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12295  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12296  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12297  }
12299  {
12300  SCIP_Real primsol;
12301  int i;
12302 
12303  assert(!var->donotmultaggr);
12304  assert(var->data.multaggr.vars != NULL);
12305  assert(var->data.multaggr.scalars != NULL);
12306  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12307  * assert(var->data.multaggr.nvars >= 2);
12308  */
12309  primsol = var->data.multaggr.constant;
12310  for( i = 0; i < var->data.multaggr.nvars; ++i )
12311  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12312  return primsol;
12313  }
12314  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12315  assert(var->negatedvar != NULL);
12317  assert(var->negatedvar->negatedvar == var);
12318  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12319 
12320  default:
12321  SCIPerrorMessage("unknown variable status\n");
12322  SCIPABORT();
12323  return SCIP_INVALID; /*lint !e527*/
12324  }
12325 }
12326 
12327 /** gets primal NLP solution value of variable */
12329  SCIP_VAR* var /**< problem variable */
12330  )
12331 {
12332  SCIP_Real solval;
12333  int i;
12334 
12335  assert(var != NULL);
12336 
12337  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12338  switch( SCIPvarGetStatus(var) )
12339  {
12341  return SCIPvarGetNLPSol(var->data.original.transvar);
12342 
12343  case SCIP_VARSTATUS_LOOSE:
12344  case SCIP_VARSTATUS_COLUMN:
12345  return var->nlpsol;
12346 
12347  case SCIP_VARSTATUS_FIXED:
12348  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12349  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12350  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12351  return SCIPvarGetLbGlobal(var);
12352 
12353  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12354  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12355  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12356 
12358  solval = var->data.multaggr.constant;
12359  for( i = 0; i < var->data.multaggr.nvars; ++i )
12360  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12361  return solval;
12362 
12364  solval = SCIPvarGetNLPSol(var->negatedvar);
12365  return var->data.negate.constant - solval;
12366 
12367  default:
12368  SCIPerrorMessage("unknown variable status\n");
12369  SCIPABORT();
12370  return SCIP_INVALID; /*lint !e527*/
12371  }
12372 }
12373 
12374 /** gets pseudo solution value of variable at current node */
12375 static
12377  SCIP_VAR* var /**< problem variable */
12378  )
12379 {
12380  SCIP_Real pseudosol;
12381  int i;
12382 
12383  assert(var != NULL);
12384 
12385  switch( SCIPvarGetStatus(var) )
12386  {
12388  if( var->data.original.transvar == NULL )
12389  return SCIP_INVALID;
12391 
12392  case SCIP_VARSTATUS_LOOSE:
12393  case SCIP_VARSTATUS_COLUMN:
12394  return SCIPvarGetBestBoundLocal(var);
12395 
12396  case SCIP_VARSTATUS_FIXED:
12397  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12398  return var->locdom.lb;
12399 
12401  {
12402  SCIP_Real pseudosolval;
12403  assert(var->data.aggregate.var != NULL);
12404  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12405  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12406  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12407  * (or is called by) a public interface method; instead, we only assert that values are finite
12408  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12409  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12410  */
12411  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12412  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12413  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12414  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12415  }
12417  assert(!var->donotmultaggr);
12418  assert(var->data.multaggr.vars != NULL);
12419  assert(var->data.multaggr.scalars != NULL);
12420  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12421  * assert(var->data.multaggr.nvars >= 2);
12422  */
12423  pseudosol = var->data.multaggr.constant;
12424  for( i = 0; i < var->data.multaggr.nvars; ++i )
12425  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12426  return pseudosol;
12427 
12428  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12429  assert(var->negatedvar != NULL);
12431  assert(var->negatedvar->negatedvar == var);
12432  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12433 
12434  default:
12435  SCIPerrorMessage("unknown variable status\n");
12436  SCIPABORT();
12437  return SCIP_INVALID; /*lint !e527*/
12438  }
12439 }
12440 
12441 /** gets current LP or pseudo solution value of variable */
12443  SCIP_VAR* var, /**< problem variable */
12444  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12445  )
12446 {
12447  if( getlpval )
12448  return SCIPvarGetLPSol(var);
12449  else
12450  return SCIPvarGetPseudoSol(var);
12451 }
12452 
12453 /** remembers the current solution as root solution in the problem variables */
12454 void SCIPvarStoreRootSol(
12455  SCIP_VAR* var, /**< problem variable */
12456  SCIP_Bool roothaslp /**< is the root solution from LP? */
12457  )
12458 {
12459  assert(var != NULL);
12460 
12461  var->rootsol = SCIPvarGetSol(var, roothaslp);
12462 }
12463 
12464 /** updates the current solution as best root solution of the given variable if it is better */
12466  SCIP_VAR* var, /**< problem variable */
12467  SCIP_SET* set, /**< global SCIP settings */
12468  SCIP_Real rootsol, /**< root solution value */
12469  SCIP_Real rootredcost, /**< root reduced cost */
12470  SCIP_Real rootlpobjval /**< objective value of the root LP */
12471  )
12472 {
12473  assert(var != NULL);
12474  assert(set != NULL);
12475  assert(var->scip == set->scip);
12476 
12477  /* if reduced cost are zero nothing to update */
12478  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12479  return;
12480 
12481  /* check if we have already a best combination stored */
12482  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12483  {
12484  SCIP_Real currcutoffbound;
12485  SCIP_Real cutoffbound;
12486  SCIP_Real bound;
12487 
12488  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12489  * root reduced cost, and root LP objective value combination
12490  */
12491  if( var->bestrootredcost > 0.0 )
12492  bound = SCIPvarGetUbGlobal(var);
12493  else
12494  bound = SCIPvarGetLbGlobal(var);
12495 
12496  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12497 
12498  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12499  * cost, and root LP objective value combination
12500  */
12501  if( rootredcost > 0.0 )
12502  bound = SCIPvarGetUbGlobal(var);
12503  else
12504  bound = SCIPvarGetLbGlobal(var);
12505 
12506  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12507 
12508  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12509  if( cutoffbound > currcutoffbound )
12510  {
12511  SCIPdebugMessage("-> <%s> update potetial cutoff bound <%g> -> <%g>\n",
12512  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12513 
12514  var->bestrootsol = rootsol;
12515  var->bestrootredcost = rootredcost;
12516  var->bestrootlpobjval = rootlpobjval;
12517  }
12518  }
12519  else
12520  {
12521  SCIPdebugMessage("-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12522  SCIPdebugMessage(" -> rootsol <%g>\n", rootsol);
12523  SCIPdebugMessage(" -> rootredcost <%g>\n", rootredcost);
12524  SCIPdebugMessage(" -> rootlpobjval <%g>\n", rootlpobjval);
12525 
12526  var->bestrootsol = rootsol;
12527  var->bestrootredcost = rootredcost;
12528  var->bestrootlpobjval = rootlpobjval;
12529  }
12530 }
12531 
12532 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12533  * completely solved, zero is returned
12534  */
12536  SCIP_VAR* var /**< problem variable */
12537  )
12538 {
12539  SCIP_Real rootsol;
12540  int i;
12541 
12542  assert(var != NULL);
12543 
12544  switch( SCIPvarGetStatus(var) )
12545  {
12547  if( var->data.original.transvar == NULL )
12548  return 0.0;
12549  return SCIPvarGetRootSol(var->data.original.transvar);
12550 
12551  case SCIP_VARSTATUS_LOOSE:
12552  case SCIP_VARSTATUS_COLUMN:
12553  return var->rootsol;
12554 
12555  case SCIP_VARSTATUS_FIXED:
12556  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12557  return var->locdom.lb;
12558 
12560  assert(var->data.aggregate.var != NULL);
12561  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12562  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12563  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12564  * (or is called by) a public interface method; instead, we only assert that values are finite
12565  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12566  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12567  */
12571 
12573  assert(!var->donotmultaggr);
12574  assert(var->data.multaggr.vars != NULL);
12575  assert(var->data.multaggr.scalars != NULL);
12576  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12577  * assert(var->data.multaggr.nvars >= 2);
12578  */
12579  rootsol = var->data.multaggr.constant;
12580  for( i = 0; i < var->data.multaggr.nvars; ++i )
12581  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12582  return rootsol;
12583 
12584  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12585  assert(var->negatedvar != NULL);
12587  assert(var->negatedvar->negatedvar == var);
12588  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12589 
12590  default:
12591  SCIPerrorMessage("unknown variable status\n");
12592  SCIPABORT();
12593  return SCIP_INVALID; /*lint !e527*/
12594  }
12595 }
12596 
12597 /** returns for given variable the reduced cost */
12599  SCIP_VAR* var, /**< problem variable */
12600  SCIP_SET* set, /**< global SCIP settings */
12601  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12602  SCIP_STAT* stat, /**< problem statistics */
12603  SCIP_LP* lp /**< current LP data */
12604  )
12605 {
12607  {
12608  SCIP_COL* col;
12609  SCIP_Real primsol;
12610  SCIP_BASESTAT basestat;
12611  SCIP_Bool lpissolbasic;
12612 
12613  col = SCIPvarGetCol(var);
12614  assert(col != NULL);
12615 
12616  basestat = SCIPcolGetBasisStatus(col);
12617  lpissolbasic = SCIPlpIsSolBasic(lp);
12618  primsol = SCIPcolGetPrimsol(col);
12619 
12620  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12621  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12622  {
12623  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12624 
12625  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12626  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12628  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12629  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12630  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12631 
12632  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12633  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12634  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12635  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12636  return redcost;
12637  else
12638  return 0.0;
12639  }
12640 
12641  return 0.0;
12642  }
12643 
12644  return 0.0;
12645 }
12646 
12647 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12648  * the binary variable is fixed to the given value
12649  */
12651  SCIP_VAR* var, /**< problem variable */
12652  SCIP_SET* set, /**< global SCIP settings */
12653  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12654  SCIP_STAT* stat, /**< problem statistics */
12655  SCIP_LP* lp /**< current LP data */
12656  )
12657 {
12658  SCIP_VAR** vars;
12659  SCIP_VAR* implvar;
12660  SCIP_BOUNDTYPE* boundtypes;
12661  SCIP_Real implredcost;
12662  SCIP_Real redcost;
12663  int nbinvars;
12664  int v;
12665 
12666  assert(SCIPvarIsBinary(var));
12667  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12668 
12669  /* get reduced cost of given variable */
12670  implredcost = SCIPvarGetRedcost(var, set, varfixing, stat, lp);
12671 
12672  /* collect binary implication information */
12673  nbinvars = SCIPimplicsGetNBinImpls(var->implics, varfixing);
12674  vars = SCIPimplicsGetVars(var->implics, varfixing);
12675  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
12676 
12677  for( v = 0; v < nbinvars; ++v )
12678  {
12679  implvar = vars[v];
12680  assert(implvar != NULL);
12681 
12682  /* ignore binary variable which are fixed */
12683  if( SCIPvarGetLbLocal(implvar) > 0.5 || SCIPvarGetUbLocal(implvar) < 0.5 )
12684  continue;
12685 
12686  assert((SCIP_Bool)SCIP_BOUNDTYPE_LOWER == FALSE);
12687  assert((SCIP_Bool)SCIP_BOUNDTYPE_UPPER == TRUE);
12688 
12689  if( (SCIP_Bool)boundtypes[v] != varfixing )
12690  redcost = SCIPvarGetRedcost(implvar, set, boundtypes[v] == SCIP_BOUNDTYPE_LOWER, stat, lp);
12691  else
12692  redcost = -SCIPvarGetRedcost(implvar, set, boundtypes[v] == SCIP_BOUNDTYPE_LOWER, stat, lp);
12693 
12694  if( !SCIPsetIsDualfeasZero(set, redcost) )
12695  implredcost += redcost;
12696  }
12697 
12698  return implredcost;
12699 }
12700 
12701 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
12702  * the root relaxation is not yet completely solved, zero is returned
12703  */
12705  SCIP_VAR* var /**< problem variable */
12706  )
12707 {
12708  SCIP_Real rootsol;
12709  int i;
12710 
12711  assert(var != NULL);
12712 
12713  switch( SCIPvarGetStatus(var) )
12714  {
12716  if( var->data.original.transvar == NULL )
12717  return 0.0;
12719 
12720  case SCIP_VARSTATUS_LOOSE:
12721  case SCIP_VARSTATUS_COLUMN:
12722  return var->bestrootsol;
12723 
12724  case SCIP_VARSTATUS_FIXED:
12725  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12726  return var->locdom.lb;
12727 
12729  assert(var->data.aggregate.var != NULL);
12730  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12731  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12732  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12733  * (or is called by) a public interface method; instead, we only assert that values are finite
12734  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12735  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12736  */
12740 
12742  assert(!var->donotmultaggr);
12743  assert(var->data.multaggr.vars != NULL);
12744  assert(var->data.multaggr.scalars != NULL);
12745  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12746  * assert(var->data.multaggr.nvars >= 2);
12747  */
12748  rootsol = var->data.multaggr.constant;
12749  for( i = 0; i < var->data.multaggr.nvars; ++i )
12750  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
12751  return rootsol;
12752 
12753  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12754  assert(var->negatedvar != NULL);
12756  assert(var->negatedvar->negatedvar == var);
12757  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
12758 
12759  default:
12760  SCIPerrorMessage("unknown variable status\n");
12761  SCIPABORT();
12762  return 0.0; /*lint !e527*/
12763  }
12764 }
12765 
12766 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
12767  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
12768  * returned
12769  */
12771  SCIP_VAR* var /**< problem variable */
12772  )
12773 {
12774  assert(var != NULL);
12775 
12776  switch( SCIPvarGetStatus(var) )
12777  {
12779  if( var->data.original.transvar == NULL )
12780  return SCIP_INVALID;
12782 
12783  case SCIP_VARSTATUS_LOOSE:
12784  case SCIP_VARSTATUS_COLUMN:
12785  return var->bestrootredcost;
12786 
12787  case SCIP_VARSTATUS_FIXED:
12791  return 0.0;
12792 
12793  default:
12794  SCIPerrorMessage("unknown variable status\n");
12795  SCIPABORT();
12796  return 0.0; /*lint !e527*/
12797  }
12798 }
12799 
12800 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
12801  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
12802  * SCIP_INVALID is returned
12803  */
12805  SCIP_VAR* var /**< problem variable */
12806  )
12807 {
12808  assert(var != NULL);
12809 
12810  switch( SCIPvarGetStatus(var) )
12811  {
12813  if( var->data.original.transvar == NULL )
12814  return SCIP_INVALID;
12816 
12817  case SCIP_VARSTATUS_LOOSE:
12818  case SCIP_VARSTATUS_COLUMN:
12819  return var->bestrootlpobjval;
12820 
12821  case SCIP_VARSTATUS_FIXED:
12825  return SCIP_INVALID;
12826 
12827  default:
12828  SCIPerrorMessage("unknown variable status\n");
12829  SCIPABORT();
12830  return SCIP_INVALID; /*lint !e527*/
12831  }
12832 }
12833 
12834 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
12836  SCIP_VAR* var, /**< problem variable */
12837  SCIP_Real rootsol, /**< root solution value */
12838  SCIP_Real rootredcost, /**< root reduced cost */
12839  SCIP_Real rootlpobjval /**< objective value of the root LP */
12840  )
12841 {
12842  assert(var != NULL);
12843 
12844  var->bestrootsol = rootsol;
12845  var->bestrootredcost = rootredcost;
12846  var->bestrootlpobjval = rootlpobjval;
12847 }
12848 
12849 /** stores the solution value as relaxation solution in the problem variable */
12851  SCIP_VAR* var, /**< problem variable */
12852  SCIP_SET* set, /**< global SCIP settings */
12853  SCIP_RELAXATION* relaxation, /**< global relaxation data */
12854  SCIP_Real solval, /**< solution value in the current relaxation solution */
12855  SCIP_Bool updateobj /**< should the objective value be updated? */
12856  )
12857 {
12858  assert(var != NULL);
12859  assert(relaxation != NULL);
12860  assert(set != NULL);
12861  assert(var->scip == set->scip);
12862 
12863  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
12864  switch( SCIPvarGetStatus(var) )
12865  {
12867  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
12868  break;
12869 
12870  case SCIP_VARSTATUS_LOOSE:
12871  case SCIP_VARSTATUS_COLUMN:
12872  if( updateobj )
12873  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
12874  var->relaxsol = solval;
12875  break;
12876 
12877  case SCIP_VARSTATUS_FIXED:
12878  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
12879  {
12880  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
12881  SCIPvarGetName(var), var->glbdom.lb, solval);
12882  return SCIP_INVALIDDATA;
12883  }
12884  break;
12885 
12886  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12887  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
12888  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
12889  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
12890  break;
12892  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
12893  return SCIP_INVALIDDATA;
12894 
12896  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
12897  break;
12898 
12899  default:
12900  SCIPerrorMessage("unknown variable status\n");
12901  return SCIP_INVALIDDATA;
12902  }
12903 
12904  return SCIP_OKAY;
12905 }
12906 
12907 /** returns the solution value of the problem variable in the relaxation solution
12908  *
12909  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
12910  */
12912  SCIP_VAR* var, /**< problem variable */
12913  SCIP_SET* set /**< global SCIP settings */
12914  )
12915 {
12916  SCIP_Real solvalsum;
12917  SCIP_Real solval;
12918  int i;
12919 
12920  assert(var != NULL);
12921  assert(set != NULL);
12922  assert(var->scip == set->scip);
12923 
12924  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12925  switch( SCIPvarGetStatus(var) )
12926  {
12928  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
12929 
12930  case SCIP_VARSTATUS_LOOSE:
12931  case SCIP_VARSTATUS_COLUMN:
12932  return var->relaxsol;
12933 
12934  case SCIP_VARSTATUS_FIXED:
12935  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12936  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12937  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12938  return SCIPvarGetLbGlobal(var);
12939 
12940  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12941  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
12942  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
12943  {
12944  if( var->data.aggregate.scalar * solval > 0.0 )
12945  return SCIPsetInfinity(set);
12946  if( var->data.aggregate.scalar * solval < 0.0 )
12947  return -SCIPsetInfinity(set);
12948  }
12949  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12950 
12952  solvalsum = var->data.multaggr.constant;
12953  for( i = 0; i < var->data.multaggr.nvars; ++i )
12954  {
12955  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
12956  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
12957  {
12958  if( var->data.multaggr.scalars[i] * solval > 0.0 )
12959  return SCIPsetInfinity(set);
12960  if( var->data.multaggr.scalars[i] * solval < 0.0 )
12961  return -SCIPsetInfinity(set);
12962  }
12963  solvalsum += var->data.multaggr.scalars[i] * solval;
12964  }
12965  return solvalsum;
12966 
12968  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
12969  if( SCIPsetIsInfinity(set, solval) )
12970  return -SCIPsetInfinity(set);
12971  if( SCIPsetIsInfinity(set, -solval) )
12972  return SCIPsetInfinity(set);
12973  return var->data.negate.constant - solval;
12974 
12975  default:
12976  SCIPerrorMessage("unknown variable status\n");
12977  SCIPABORT();
12978  return SCIP_INVALID; /*lint !e527*/
12979  }
12980 }
12981 
12982 /** returns the solution value of the transformed problem variable in the relaxation solution */
12984  SCIP_VAR* var /**< problem variable */
12985  )
12986 {
12987  assert(var != NULL);
12989 
12990  return var->relaxsol;
12991 }
12992 
12993 /** stores the solution value as NLP solution in the problem variable */
12995  SCIP_VAR* var, /**< problem variable */
12996  SCIP_SET* set, /**< global SCIP settings */
12997  SCIP_Real solval /**< solution value in the current NLP solution */
12998  )
12999 {
13000  assert(var != NULL);
13001  assert(set != NULL);
13002  assert(var->scip == set->scip);
13003 
13004  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13005  switch( SCIPvarGetStatus(var) )
13006  {
13008  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13009  break;
13010 
13011  case SCIP_VARSTATUS_LOOSE:
13012  case SCIP_VARSTATUS_COLUMN:
13013  var->nlpsol = solval;
13014  break;
13015 
13016  case SCIP_VARSTATUS_FIXED:
13017  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13018  {
13019  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13020  SCIPvarGetName(var), var->glbdom.lb, solval);
13021  SCIPABORT();
13022  return SCIP_INVALIDCALL; /*lint !e527*/
13023  }
13024  break;
13025 
13026  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13027  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13028  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13029  break;
13030 
13032  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13033  SCIPABORT();
13034  return SCIP_INVALIDCALL; /*lint !e527*/
13035 
13037  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13038  break;
13039 
13040  default:
13041  SCIPerrorMessage("unknown variable status\n");
13042  SCIPABORT();
13043  return SCIP_ERROR; /*lint !e527*/
13044  }
13045 
13046  return SCIP_OKAY;
13047 }
13048 
13049 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13051  SCIP_VAR* var /**< problem variable */
13052  )
13053 {
13054  SCIP_Real avgsol;
13055  int i;
13056 
13057  assert(var != NULL);
13058 
13059  switch( SCIPvarGetStatus(var) )
13060  {
13062  if( var->data.original.transvar == NULL )
13063  return 0.0;
13064  return SCIPvarGetAvgSol(var->data.original.transvar);
13065 
13066  case SCIP_VARSTATUS_LOOSE:
13067  case SCIP_VARSTATUS_COLUMN:
13068  avgsol = var->primsolavg;
13069  avgsol = MAX(avgsol, var->glbdom.lb);
13070  avgsol = MIN(avgsol, var->glbdom.ub);
13071  return avgsol;
13072 
13073  case SCIP_VARSTATUS_FIXED:
13074  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13075  return var->locdom.lb;
13076 
13078  assert(var->data.aggregate.var != NULL);
13079  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13080  + var->data.aggregate.constant;
13081 
13083  assert(!var->donotmultaggr);
13084  assert(var->data.multaggr.vars != NULL);
13085  assert(var->data.multaggr.scalars != NULL);
13086  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13087  * assert(var->data.multaggr.nvars >= 2);
13088  */
13089  avgsol = var->data.multaggr.constant;
13090  for( i = 0; i < var->data.multaggr.nvars; ++i )
13091  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13092  return avgsol;
13093 
13094  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13095  assert(var->negatedvar != NULL);
13097  assert(var->negatedvar->negatedvar == var);
13098  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13099 
13100  default:
13101  SCIPerrorMessage("unknown variable status\n");
13102  SCIPABORT();
13103  return 0.0; /*lint !e527*/
13104  }
13105 }
13106 
13107 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13108  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13109  */
13111  SCIP_VAR* var, /**< active problem variable */
13112  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13113  SCIP_SET* set, /**< global SCIP settings */
13114  SCIP_STAT* stat, /**< problem statistics */
13115  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13116  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13117  )
13118 {
13119  int nvlbs;
13120 
13121  assert(var != NULL);
13122  assert(stat != NULL);
13123  assert(set != NULL);
13124  assert(var->scip == set->scip);
13125  assert(closestvlb != NULL);
13126  assert(closestvlbidx != NULL);
13127 
13128  *closestvlbidx = -1;
13129  *closestvlb = SCIP_REAL_MIN;
13130 
13131  nvlbs = SCIPvarGetNVlbs(var);
13132  if( nvlbs > 0 )
13133  {
13134  SCIP_VAR** vlbvars;
13135  SCIP_Real* vlbcoefs;
13136  SCIP_Real* vlbconsts;
13137  int i;
13138 
13139  vlbvars = SCIPvarGetVlbVars(var);
13140  vlbcoefs = SCIPvarGetVlbCoefs(var);
13141  vlbconsts = SCIPvarGetVlbConstants(var);
13142 
13143  /* check for cached values */
13144  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13145  {
13146  i = var->closestvlbidx;
13147  assert(0 <= i && i < nvlbs);
13148  assert(SCIPvarIsActive(vlbvars[i]));
13149  *closestvlbidx = i;
13150  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13151  }
13152  else
13153  {
13154  /* search best VUB */
13155  for( i = 0; i < nvlbs; i++ )
13156  {
13157  if( SCIPvarIsActive(vlbvars[i]) )
13158  {
13159  SCIP_Real vlbsol;
13160 
13161  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13162  if( vlbsol > *closestvlb )
13163  {
13164  *closestvlb = vlbsol;
13165  *closestvlbidx = i;
13166  }
13167  }
13168  }
13169 
13170  if( sol == NULL )
13171  {
13172  /* update cached value */
13173  if( var->closestvblpcount != stat->lpcount )
13174  var->closestvubidx = -1;
13175  var->closestvlbidx = *closestvlbidx;
13176  var->closestvblpcount = stat->lpcount;
13177  }
13178  }
13179  }
13180 }
13181 
13182 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13183  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13184  */
13186  SCIP_VAR* var, /**< active problem variable */
13187  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13188  SCIP_SET* set, /**< global SCIP settings */
13189  SCIP_STAT* stat, /**< problem statistics */
13190  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13191  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13192  )
13193 {
13194  int nvubs;
13195 
13196  assert(var != NULL);
13197  assert(set != NULL);
13198  assert(var->scip == set->scip);
13199  assert(closestvub != NULL);
13200  assert(closestvubidx != NULL);
13201 
13202  *closestvubidx = -1;
13203  *closestvub = SCIP_REAL_MAX;
13204 
13205  nvubs = SCIPvarGetNVubs(var);
13206  if( nvubs > 0 )
13207  {
13208  SCIP_VAR** vubvars;
13209  SCIP_Real* vubcoefs;
13210  SCIP_Real* vubconsts;
13211  int i;
13212 
13213  vubvars = SCIPvarGetVubVars(var);
13214  vubcoefs = SCIPvarGetVubCoefs(var);
13215  vubconsts = SCIPvarGetVubConstants(var);
13216 
13217  /* check for cached values */
13218  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13219  {
13220  i = var->closestvubidx;
13221  assert(0 <= i && i < nvubs);
13222  assert(SCIPvarIsActive(vubvars[i]));
13223  *closestvubidx = i;
13224  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13225  }
13226  else
13227  {
13228  /* search best VUB */
13229  for( i = 0; i < nvubs; i++ )
13230  {
13231  if( SCIPvarIsActive(vubvars[i]) )
13232  {
13233  SCIP_Real vubsol;
13234 
13235  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13236  if( vubsol < *closestvub )
13237  {
13238  *closestvub = vubsol;
13239  *closestvubidx = i;
13240  }
13241  }
13242  }
13243 
13244  if( sol == NULL )
13245  {
13246  /* update cached value */
13247  if( var->closestvblpcount != stat->lpcount )
13248  var->closestvlbidx = -1;
13249  var->closestvubidx = *closestvubidx;
13250  var->closestvblpcount = stat->lpcount;
13251  }
13252  }
13253  }
13254 }
13255 
13256 /** resolves variable to columns and adds them with the coefficient to the row */
13258  SCIP_VAR* var, /**< problem variable */
13259  BMS_BLKMEM* blkmem, /**< block memory */
13260  SCIP_SET* set, /**< global SCIP settings */
13261  SCIP_STAT* stat, /**< problem statistics */
13262  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13263  SCIP_PROB* prob, /**< problem data */
13264  SCIP_LP* lp, /**< current LP data */
13265  SCIP_ROW* row, /**< LP row */
13266  SCIP_Real val /**< value of coefficient */
13267  )
13268 {
13269  int i;
13270 
13271  assert(var != NULL);
13272  assert(set != NULL);
13273  assert(var->scip == set->scip);
13274  assert(row != NULL);
13275  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13276 
13277  SCIPdebugMessage("adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13278 
13279  if ( SCIPsetIsZero(set, val) )
13280  return SCIP_OKAY;
13281 
13282  switch( SCIPvarGetStatus(var) )
13283  {
13285  if( var->data.original.transvar == NULL )
13286  {
13287  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13288  return SCIP_INVALIDDATA;
13289  }
13290  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13291  return SCIP_OKAY;
13292 
13293  case SCIP_VARSTATUS_LOOSE:
13294  /* add globally fixed variables as constant */
13295  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13296  {
13297  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13298  return SCIP_OKAY;
13299  }
13300  /* convert loose variable into column */
13301  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13302  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13303  /*lint -fallthrough*/
13304 
13305  case SCIP_VARSTATUS_COLUMN:
13306  assert(var->data.col != NULL);
13307  assert(var->data.col->var == var);
13308  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13309  return SCIP_OKAY;
13310 
13311  case SCIP_VARSTATUS_FIXED:
13312  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13313  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13314  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13315  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13316  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13317  return SCIP_OKAY;
13318 
13320  assert(var->data.aggregate.var != NULL);
13321  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13322  row, var->data.aggregate.scalar * val) );
13323  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13324  return SCIP_OKAY;
13325 
13327  assert(!var->donotmultaggr);
13328  assert(var->data.multaggr.vars != NULL);
13329  assert(var->data.multaggr.scalars != NULL);
13330  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13331  * assert(var->data.multaggr.nvars >= 2);
13332  */
13333  for( i = 0; i < var->data.multaggr.nvars; ++i )
13334  {
13335  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13336  row, var->data.multaggr.scalars[i] * val) );
13337  }
13338  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13339  return SCIP_OKAY;
13340 
13341  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13342  assert(var->negatedvar != NULL);
13344  assert(var->negatedvar->negatedvar == var);
13345  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13346  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13347  return SCIP_OKAY;
13348 
13349  default:
13350  SCIPerrorMessage("unknown variable status\n");
13351  return SCIP_INVALIDDATA;
13352  }
13353 }
13354 
13355 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13356  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13357  */
13359  SCIP_VAR* var, /**< problem variable */
13360  SCIP_SET* set, /**< global SCIP settings */
13361  SCIP_STAT* stat, /**< problem statistics */
13362  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13363  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13364  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13365  )
13366 {
13367  assert(var != NULL);
13368  assert(set != NULL);
13369  assert(var->scip == set->scip);
13370  assert(stat != NULL);
13371 
13372  /* check if history statistics should be collected for a variable */
13373  if( !stat->collectvarhistory )
13374  return SCIP_OKAY;
13375 
13376  switch( SCIPvarGetStatus(var) )
13377  {
13379  if( var->data.original.transvar == NULL )
13380  {
13381  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13382  return SCIP_INVALIDDATA;
13383  }
13384  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13385  return SCIP_OKAY;
13386 
13387  case SCIP_VARSTATUS_LOOSE:
13388  case SCIP_VARSTATUS_COLUMN:
13389  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13390  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13391  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13392  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13393  return SCIP_OKAY;
13394 
13395  case SCIP_VARSTATUS_FIXED:
13396  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13397  return SCIP_INVALIDDATA;
13398 
13400  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13402  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13403  return SCIP_OKAY;
13404 
13406  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13407  return SCIP_INVALIDDATA;
13408 
13410  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13411  return SCIP_OKAY;
13412 
13413  default:
13414  SCIPerrorMessage("unknown variable status\n");
13415  return SCIP_INVALIDDATA;
13416  }
13417 }
13418 
13419 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13421  SCIP_VAR* var, /**< problem variable */
13422  SCIP_STAT* stat, /**< problem statistics */
13423  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13424  )
13425 {
13426  SCIP_BRANCHDIR dir;
13427 
13428  assert(var != NULL);
13429  assert(stat != NULL);
13430 
13431  switch( SCIPvarGetStatus(var) )
13432  {
13434  if( var->data.original.transvar == NULL )
13435  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13436  else
13437  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13438 
13439  case SCIP_VARSTATUS_LOOSE:
13440  case SCIP_VARSTATUS_COLUMN:
13441  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13442 
13443  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13444  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13445  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13446 
13447  case SCIP_VARSTATUS_FIXED:
13448  return 0.0;
13449 
13451  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13452 
13454  return 0.0;
13455 
13457  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13458 
13459  default:
13460  SCIPerrorMessage("unknown variable status\n");
13461  SCIPABORT();
13462  return 0.0; /*lint !e527*/
13463  }
13464 }
13465 
13466 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13467  * only using the pseudo cost information of the current run
13468  */
13470  SCIP_VAR* var, /**< problem variable */
13471  SCIP_STAT* stat, /**< problem statistics */
13472  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13473  )
13474 {
13475  SCIP_BRANCHDIR dir;
13476 
13477  assert(var != NULL);
13478  assert(stat != NULL);
13479 
13480  switch( SCIPvarGetStatus(var) )
13481  {
13483  if( var->data.original.transvar == NULL )
13484  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13485  else
13486  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
13487 
13488  case SCIP_VARSTATUS_LOOSE:
13489  case SCIP_VARSTATUS_COLUMN:
13490  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13491 
13492  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
13493  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
13494  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13495 
13496  case SCIP_VARSTATUS_FIXED:
13497  return 0.0;
13498 
13500  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13501 
13503  return 0.0;
13504 
13506  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
13507 
13508  default:
13509  SCIPerrorMessage("unknown variable status\n");
13510  SCIPABORT();
13511  return 0.0; /*lint !e527*/
13512  }
13513 }
13514 
13515 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
13517  SCIP_VAR* var, /**< problem variable */
13518  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13519  )
13520 {
13521  assert(var != NULL);
13522  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13523 
13524  switch( SCIPvarGetStatus(var) )
13525  {
13527  if( var->data.original.transvar == NULL )
13528  return 0.0;
13529  else
13530  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
13531 
13532  case SCIP_VARSTATUS_LOOSE:
13533  case SCIP_VARSTATUS_COLUMN:
13534  return SCIPhistoryGetPseudocostCount(var->history, dir);
13535 
13536  case SCIP_VARSTATUS_FIXED:
13537  return 0.0;
13538 
13540  if( var->data.aggregate.scalar > 0.0 )
13541  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
13542  else
13544 
13546  return 0.0;
13547 
13550 
13551  default:
13552  SCIPerrorMessage("unknown variable status\n");
13553  SCIPABORT();
13554  return 0.0; /*lint !e527*/
13555  }
13556 }
13557 
13558 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
13559  * only using the pseudo cost information of the current run
13560  */
13562  SCIP_VAR* var, /**< problem variable */
13563  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13564  )
13565 {
13566  assert(var != NULL);
13567  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13568 
13569  switch( SCIPvarGetStatus(var) )
13570  {
13572  if( var->data.original.transvar == NULL )
13573  return 0.0;
13574  else
13576 
13577  case SCIP_VARSTATUS_LOOSE:
13578  case SCIP_VARSTATUS_COLUMN:
13579  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
13580 
13581  case SCIP_VARSTATUS_FIXED:
13582  return 0.0;
13583 
13585  if( var->data.aggregate.scalar > 0.0 )
13587  else
13589 
13591  return 0.0;
13592 
13595 
13596  default:
13597  SCIPerrorMessage("unknown variable status\n");
13598  SCIPABORT();
13599  return 0.0; /*lint !e527*/
13600  }
13601 }
13602 
13603 /** find the corresponding history entry if already existing, otherwise create new entry */
13604 static
13606  SCIP_VAR* var, /**< problem variable */
13607  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
13608  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
13609  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
13610  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
13611  )
13612 {
13613  assert(var != NULL);
13614  assert(blkmem != NULL);
13615  assert(set != NULL);
13616  assert(history != NULL);
13617 
13618  (*history) = NULL;
13619 
13620  if( var->valuehistory == NULL )
13621  {
13622  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
13623  }
13624 
13625  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
13626 
13627  return SCIP_OKAY;
13628 }
13629 
13630 /** check if value based history should be used */
13631 static
13633  SCIP_VAR* var, /**< problem variable */
13634  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
13635  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
13636  )
13637 {
13638  /* check if the domain value is unknown (not specific) */
13639  if( value == SCIP_UNKNOWN ) /*lint !e777*/
13640  return FALSE;
13641 
13642  assert(set != NULL);
13643 
13644  /* check if value based history should be collected */
13645  if( !set->history_valuebased )
13646  return FALSE;
13647 
13648  /* value based history is not collected for binary variable since the standard history already contains all information */
13649  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
13650  return FALSE;
13651 
13652  /* value based history is not collected for continuous variables */
13654  return FALSE;
13655 
13656  return TRUE;
13657 }
13658 
13659 /** increases VSIDS of the variable by the given weight */
13661  SCIP_VAR* var, /**< problem variable */
13662  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
13663  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
13664  SCIP_STAT* stat, /**< problem statistics */
13665  SCIP_BRANCHDIR dir, /**< branching direction */
13666  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
13667  SCIP_Real weight /**< weight of this update in VSIDS */
13668  )
13669 {
13670  assert(var != NULL);
13671  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13672 
13673  /* check if history statistics should be collected for a variable */
13674  if( !stat->collectvarhistory )
13675  return SCIP_OKAY;
13676 
13677  if( SCIPsetIsZero(set, weight) )
13678  return SCIP_OKAY;
13679 
13680  switch( SCIPvarGetStatus(var) )
13681  {
13683  if( var->data.original.transvar == NULL )
13684  {
13685  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
13686  return SCIP_INVALIDDATA;
13687  }
13688  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
13689  return SCIP_OKAY;
13690 
13691  case SCIP_VARSTATUS_LOOSE:
13692  case SCIP_VARSTATUS_COLUMN:
13693  {
13694  SCIPhistoryIncVSIDS(var->history, dir, weight);
13695  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
13696 
13697  if( useValuehistory(var, value, set) )
13698  {
13699  SCIP_HISTORY* history;
13700 
13701  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
13702  assert(history != NULL);
13703 
13704  SCIPhistoryIncVSIDS(history, dir, weight);
13705  SCIPdebugMessage("variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
13706  value, weight, SCIPhistoryGetVSIDS(history, dir));
13707  }
13708 
13709  return SCIP_OKAY;
13710  }
13711  case SCIP_VARSTATUS_FIXED:
13712  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
13713  return SCIP_INVALIDDATA;
13714 
13716  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
13717 
13718  if( var->data.aggregate.scalar > 0.0 )
13719  {
13720  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
13721  }
13722  else
13723  {
13724  assert(var->data.aggregate.scalar < 0.0);
13725  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
13726  }
13727  return SCIP_OKAY;
13728 
13730  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
13731  return SCIP_INVALIDDATA;
13732 
13734  value = 1.0 - value;
13735 
13736  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
13737  return SCIP_OKAY;
13738 
13739  default:
13740  SCIPerrorMessage("unknown variable status\n");
13741  return SCIP_INVALIDDATA;
13742  }
13743 }
13744 
13745 /** scales the VSIDS of the variable by the given scalar */
13747  SCIP_VAR* var, /**< problem variable */
13748  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
13749  )
13750 {
13751  assert(var != NULL);
13752 
13753  switch( SCIPvarGetStatus(var) )
13754  {
13756  if( var->data.original.transvar == NULL )
13757  {
13758  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
13759  return SCIP_INVALIDDATA;
13760  }
13762  return SCIP_OKAY;
13763 
13764  case SCIP_VARSTATUS_LOOSE:
13765  case SCIP_VARSTATUS_COLUMN:
13766  {
13767  SCIPhistoryScaleVSIDS(var->history, scalar);
13768  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
13770 
13771  return SCIP_OKAY;
13772  }
13773  case SCIP_VARSTATUS_FIXED:
13774  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
13775  return SCIP_INVALIDDATA;
13776 
13778  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
13779  return SCIP_OKAY;
13780 
13782  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
13783  return SCIP_INVALIDDATA;
13784 
13786  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
13787  return SCIP_OKAY;
13788 
13789  default:
13790  SCIPerrorMessage("unknown variable status\n");
13791  return SCIP_INVALIDDATA;
13792  }
13793 }
13794 
13795 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
13797  SCIP_VAR* var, /**< problem variable */
13798  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
13799  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
13800  SCIP_STAT* stat, /**< problem statistics */
13801  SCIP_BRANCHDIR dir, /**< branching direction */
13802  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
13803  SCIP_Real length /**< length of the conflict */
13804  )
13805 {
13806  assert(var != NULL);
13807  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13808 
13809  /* check if history statistics should be collected for a variable */
13810  if( !stat->collectvarhistory )
13811  return SCIP_OKAY;
13812 
13813  switch( SCIPvarGetStatus(var) )
13814  {
13816  if( var->data.original.transvar == NULL )
13817  {
13818  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
13819  return SCIP_INVALIDDATA;
13820  }
13821  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
13822  return SCIP_OKAY;
13823 
13824  case SCIP_VARSTATUS_LOOSE:
13825  case SCIP_VARSTATUS_COLUMN:
13826  {
13827  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
13828  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
13829 
13830  if( useValuehistory(var, value, set) )
13831  {
13832  SCIP_HISTORY* history;
13833 
13834  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
13835  assert(history != NULL);
13836 
13837  SCIPhistoryIncNActiveConflicts(history, dir, length);
13838  }
13839 
13840  return SCIP_OKAY;
13841  }
13842  case SCIP_VARSTATUS_FIXED:
13843  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
13844  return SCIP_INVALIDDATA;
13845 
13847  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
13848 
13849  if( var->data.aggregate.scalar > 0.0 )
13850  {
13851  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
13852  }
13853  else
13854  {
13855  assert(var->data.aggregate.scalar < 0.0);
13856  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
13857  }
13858  return SCIP_OKAY;
13859 
13861  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
13862  return SCIP_INVALIDDATA;
13863 
13865  value = 1.0 - value;
13866 
13867  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
13868  return SCIP_OKAY;
13869 
13870  default:
13871  SCIPerrorMessage("unknown variable status\n");
13872  return SCIP_INVALIDDATA;
13873  }
13874 }
13875 
13876 /** gets the number of active conflicts containing this variable in given direction */
13878  SCIP_VAR* var, /**< problem variable */
13879  SCIP_STAT* stat, /**< problem statistics */
13880  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13881  )
13882 {
13883  assert(var != NULL);
13884  assert(stat != NULL);
13885  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13886 
13887  switch( SCIPvarGetStatus(var) )
13888  {
13890  if( var->data.original.transvar == NULL )
13891  return 0;
13892  else
13893  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
13894 
13895  case SCIP_VARSTATUS_LOOSE:
13896  case SCIP_VARSTATUS_COLUMN:
13897  return SCIPhistoryGetNActiveConflicts(var->history, dir);
13898 
13899  case SCIP_VARSTATUS_FIXED:
13900  return 0;
13901 
13903  if( var->data.aggregate.scalar > 0.0 )
13904  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
13905  else
13907 
13909  return 0;
13910 
13913 
13914  default:
13915  SCIPerrorMessage("unknown variable status\n");
13916  SCIPABORT();
13917  return 0; /*lint !e527*/
13918  }
13919 }
13920 
13921 /** gets the number of active conflicts containing this variable in given direction
13922  * in the current run
13923  */
13925  SCIP_VAR* var, /**< problem variable */
13926  SCIP_STAT* stat, /**< problem statistics */
13927  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13928  )
13929 {
13930  assert(var != NULL);
13931  assert(stat != NULL);
13932  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13933 
13934  switch( SCIPvarGetStatus(var) )
13935  {
13937  if( var->data.original.transvar == NULL )
13938  return 0;
13939  else
13941 
13942  case SCIP_VARSTATUS_LOOSE:
13943  case SCIP_VARSTATUS_COLUMN:
13944  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
13945 
13946  case SCIP_VARSTATUS_FIXED:
13947  return 0;
13948 
13950  if( var->data.aggregate.scalar > 0.0 )
13951  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
13952  else
13954 
13956  return 0;
13957 
13960 
13961  default:
13962  SCIPerrorMessage("unknown variable status\n");
13963  SCIPABORT();
13964  return 0; /*lint !e527*/
13965  }
13966 }
13967 
13968 /** gets the average conflict length in given direction due to branching on the variable */
13970  SCIP_VAR* var, /**< problem variable */
13971  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13972  )
13973 {
13974  assert(var != NULL);
13975  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13976 
13977  switch( SCIPvarGetStatus(var) )
13978  {
13980  if( var->data.original.transvar == NULL )
13981  return 0.0;
13982  else
13984 
13985  case SCIP_VARSTATUS_LOOSE:
13986  case SCIP_VARSTATUS_COLUMN:
13987  return SCIPhistoryGetAvgConflictlength(var->history, dir);
13988  case SCIP_VARSTATUS_FIXED:
13989  return 0.0;
13990 
13992  if( var->data.aggregate.scalar > 0.0 )
13993  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
13994  else
13996 
13998  return 0.0;
13999 
14002 
14003  default:
14004  SCIPerrorMessage("unknown variable status\n");
14005  SCIPABORT();
14006  return 0.0; /*lint !e527*/
14007  }
14008 }
14009 
14010 /** gets the average conflict length in given direction due to branching on the variable
14011  * in the current run
14012  */
14014  SCIP_VAR* var, /**< problem variable */
14015  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14016  )
14017 {
14018  assert(var != NULL);
14019  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14020 
14021  switch( SCIPvarGetStatus(var) )
14022  {
14024  if( var->data.original.transvar == NULL )
14025  return 0.0;
14026  else
14028 
14029  case SCIP_VARSTATUS_LOOSE:
14030  case SCIP_VARSTATUS_COLUMN:
14031  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14032 
14033  case SCIP_VARSTATUS_FIXED:
14034  return 0.0;
14035 
14037  if( var->data.aggregate.scalar > 0.0 )
14039  else
14041 
14043  return 0.0;
14044 
14047 
14048  default:
14049  SCIPerrorMessage("unknown variable status\n");
14050  SCIPABORT();
14051  return 0.0; /*lint !e527*/
14052  }
14053 }
14054 
14055 /** increases the number of branchings counter of the variable */
14057  SCIP_VAR* var, /**< problem variable */
14058  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14059  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14060  SCIP_STAT* stat, /**< problem statistics */
14061  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14062  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14063  int depth /**< depth at which the bound change took place */
14064  )
14065 {
14066  assert(var != NULL);
14067  assert(stat != NULL);
14068  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14069 
14070  /* check if history statistics should be collected for a variable */
14071  if( !stat->collectvarhistory )
14072  return SCIP_OKAY;
14073 
14074  switch( SCIPvarGetStatus(var) )
14075  {
14077  if( var->data.original.transvar == NULL )
14078  {
14079  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14080  return SCIP_INVALIDDATA;
14081  }
14082  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14083  return SCIP_OKAY;
14084 
14085  case SCIP_VARSTATUS_LOOSE:
14086  case SCIP_VARSTATUS_COLUMN:
14087  {
14088  SCIPhistoryIncNBranchings(var->history, dir, depth);
14089  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14090  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14091  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14092 
14093  if( useValuehistory(var, value, set) )
14094  {
14095  SCIP_HISTORY* history;
14096 
14097  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14098  assert(history != NULL);
14099 
14100  SCIPhistoryIncNBranchings(history, dir, depth);
14101  }
14102 
14103  return SCIP_OKAY;
14104  }
14105  case SCIP_VARSTATUS_FIXED:
14106  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14107  return SCIP_INVALIDDATA;
14108 
14110  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14111 
14112  if( var->data.aggregate.scalar > 0.0 )
14113  {
14114  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14115  }
14116  else
14117  {
14118  assert(var->data.aggregate.scalar < 0.0);
14119  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14120  }
14121  return SCIP_OKAY;
14122 
14124  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14125  return SCIP_INVALIDDATA;
14126 
14128  value = 1.0 - value;
14129 
14130  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14131  return SCIP_OKAY;
14132 
14133  default:
14134  SCIPerrorMessage("unknown variable status\n");
14135  return SCIP_INVALIDDATA;
14136  }
14137 }
14138 
14139 /** increases the inference sum of the variable by the given weight */
14141  SCIP_VAR* var, /**< problem variable */
14142  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14143  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14144  SCIP_STAT* stat, /**< problem statistics */
14145  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14146  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14147  SCIP_Real weight /**< weight of this update in inference score */
14148  )
14149 {
14150  assert(var != NULL);
14151  assert(stat != NULL);
14152  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14153 
14154  /* check if history statistics should be collected for a variable */
14155  if( !stat->collectvarhistory )
14156  return SCIP_OKAY;
14157 
14158  switch( SCIPvarGetStatus(var) )
14159  {
14161  if( var->data.original.transvar == NULL )
14162  {
14163  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
14164  return SCIP_INVALIDDATA;
14165  }
14166  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14167  return SCIP_OKAY;
14168 
14169  case SCIP_VARSTATUS_LOOSE:
14170  case SCIP_VARSTATUS_COLUMN:
14171  {
14172  SCIPhistoryIncInferenceSum(var->history, dir, weight);
14173  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
14174  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
14175  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
14176 
14177  if( useValuehistory(var, value, set) )
14178  {
14179  SCIP_HISTORY* history;
14180 
14181  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14182  assert(history != NULL);
14183 
14184  SCIPhistoryIncInferenceSum(history, dir, weight);
14185  }
14186 
14187  return SCIP_OKAY;
14188  }
14189  case SCIP_VARSTATUS_FIXED:
14190  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
14191  return SCIP_INVALIDDATA;
14192 
14194  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14195 
14196  if( var->data.aggregate.scalar > 0.0 )
14197  {
14198  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14199  }
14200  else
14201  {
14202  assert(var->data.aggregate.scalar < 0.0);
14203  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14204  }
14205  return SCIP_OKAY;
14206 
14208  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
14209  return SCIP_INVALIDDATA;
14210 
14212  value = 1.0 - value;
14213 
14214  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14215  return SCIP_OKAY;
14216 
14217  default:
14218  SCIPerrorMessage("unknown variable status\n");
14219  return SCIP_INVALIDDATA;
14220  }
14221 }
14222 
14223 /** increases the cutoff sum of the variable by the given weight */
14225  SCIP_VAR* var, /**< problem variable */
14226  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14227  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14228  SCIP_STAT* stat, /**< problem statistics */
14229  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14230  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14231  SCIP_Real weight /**< weight of this update in cutoff score */
14232  )
14233 {
14234  assert(var != NULL);
14235  assert(stat != NULL);
14236  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14237 
14238  /* check if history statistics should be collected for a variable */
14239  if( !stat->collectvarhistory )
14240  return SCIP_OKAY;
14241 
14242  switch( SCIPvarGetStatus(var) )
14243  {
14245  if( var->data.original.transvar == NULL )
14246  {
14247  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
14248  return SCIP_INVALIDDATA;
14249  }
14250  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14251  return SCIP_OKAY;
14252 
14253  case SCIP_VARSTATUS_LOOSE:
14254  case SCIP_VARSTATUS_COLUMN:
14255  {
14256  SCIPhistoryIncCutoffSum(var->history, dir, weight);
14257  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
14258  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
14259  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
14260 
14261  if( useValuehistory(var, value, set) )
14262  {
14263  SCIP_HISTORY* history;
14264 
14265  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14266  assert(history != NULL);
14267 
14268  SCIPhistoryIncCutoffSum(history, dir, weight);
14269  }
14270 
14271  return SCIP_OKAY;
14272  }
14273  case SCIP_VARSTATUS_FIXED:
14274  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
14275  return SCIP_INVALIDDATA;
14276 
14278  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14279 
14280  if( var->data.aggregate.scalar > 0.0 )
14281  {
14282  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14283  }
14284  else
14285  {
14286  assert(var->data.aggregate.scalar < 0.0);
14287  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14288  }
14289  return SCIP_OKAY;
14290 
14292  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
14293  return SCIP_INVALIDDATA;
14294 
14296  value = 1.0 - value;
14297 
14298  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14299  return SCIP_OKAY;
14300 
14301  default:
14302  SCIPerrorMessage("unknown variable status\n");
14303  return SCIP_INVALIDDATA;
14304  }
14305 }
14306 
14307 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
14309  SCIP_VAR* var, /**< problem variable */
14310  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14311  )
14312 {
14313  assert(var != NULL);
14314  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14315 
14316  switch( SCIPvarGetStatus(var) )
14317  {
14319  if( var->data.original.transvar == NULL )
14320  return 0;
14321  else
14322  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
14323 
14324  case SCIP_VARSTATUS_LOOSE:
14325  case SCIP_VARSTATUS_COLUMN:
14326  return SCIPhistoryGetNBranchings(var->history, dir);
14327 
14328  case SCIP_VARSTATUS_FIXED:
14329  return 0;
14330 
14332  if( var->data.aggregate.scalar > 0.0 )
14333  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
14334  else
14336 
14338  return 0;
14339 
14342 
14343  default:
14344  SCIPerrorMessage("unknown variable status\n");
14345  SCIPABORT();
14346  return 0; /*lint !e527*/
14347  }
14348 }
14349 
14350 /** returns the number of times, a bound of the variable was changed in given direction due to branching
14351  * in the current run
14352  */
14354  SCIP_VAR* var, /**< problem variable */
14355  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14356  )
14357 {
14358  assert(var != NULL);
14359  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14360 
14361  switch( SCIPvarGetStatus(var) )
14362  {
14364  if( var->data.original.transvar == NULL )
14365  return 0;
14366  else
14368 
14369  case SCIP_VARSTATUS_LOOSE:
14370  case SCIP_VARSTATUS_COLUMN:
14371  return SCIPhistoryGetNBranchings(var->historycrun, dir);
14372 
14373  case SCIP_VARSTATUS_FIXED:
14374  return 0;
14375 
14377  if( var->data.aggregate.scalar > 0.0 )
14379  else
14381 
14383  return 0;
14384 
14387 
14388  default:
14389  SCIPerrorMessage("unknown variable status\n");
14390  SCIPABORT();
14391  return 0; /*lint !e527*/
14392  }
14393 }
14394 
14395 /** returns the average depth of bound changes in given direction due to branching on the variable */
14397  SCIP_VAR* var, /**< problem variable */
14398  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14399  )
14400 {
14401  assert(var != NULL);
14402  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14403 
14404  switch( SCIPvarGetStatus(var) )
14405  {
14407  if( var->data.original.transvar == NULL )
14408  return 0.0;
14409  else
14410  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
14411 
14412  case SCIP_VARSTATUS_LOOSE:
14413  case SCIP_VARSTATUS_COLUMN:
14414  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
14415 
14416  case SCIP_VARSTATUS_FIXED:
14417  return 0.0;
14418 
14420  if( var->data.aggregate.scalar > 0.0 )
14421  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
14422  else
14424 
14426  return 0.0;
14427 
14430 
14431  default:
14432  SCIPerrorMessage("unknown variable status\n");
14433  SCIPABORT();
14434  return 0.0; /*lint !e527*/
14435  }
14436 }
14437 
14438 /** returns the average depth of bound changes in given direction due to branching on the variable
14439  * in the current run
14440  */
14442  SCIP_VAR* var, /**< problem variable */
14443  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14444  )
14445 {
14446  assert(var != NULL);
14447  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14448 
14449  switch( SCIPvarGetStatus(var) )
14450  {
14452  if( var->data.original.transvar == NULL )
14453  return 0.0;
14454  else
14456 
14457  case SCIP_VARSTATUS_LOOSE:
14458  case SCIP_VARSTATUS_COLUMN:
14459  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
14460 
14461  case SCIP_VARSTATUS_FIXED:
14462  return 0.0;
14463 
14465  if( var->data.aggregate.scalar > 0.0 )
14467  else
14469 
14471  return 0.0;
14472 
14475 
14476  default:
14477  SCIPerrorMessage("unknown variable status\n");
14478  SCIPABORT();
14479  return 0.0; /*lint !e527*/
14480  }
14481 }
14482 
14483 /** returns the variable's VSIDS score */
14485  SCIP_VAR* var, /**< problem variable */
14486  SCIP_STAT* stat, /**< problem statistics */
14487  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14488  )
14489 {
14490  assert(var != NULL);
14491  assert(stat != NULL);
14492  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14493 
14495  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
14496 
14497  switch( SCIPvarGetStatus(var) )
14498  {
14500  if( var->data.original.transvar == NULL )
14501  return 0.0;
14502  else
14503  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
14504 
14505  case SCIP_VARSTATUS_LOOSE:
14506  case SCIP_VARSTATUS_COLUMN:
14507  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
14508  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
14509 
14510  case SCIP_VARSTATUS_FIXED:
14511  return 0.0;
14512 
14514  if( var->data.aggregate.scalar > 0.0 )
14515  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
14516  else
14517  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
14518 
14520  return 0.0;
14521 
14523  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
14524 
14525  default:
14526  SCIPerrorMessage("unknown variable status\n");
14527  SCIPABORT();
14528  return 0.0; /*lint !e527*/
14529  }
14530 }
14531 
14532 /** returns the variable's VSIDS score only using conflicts of the current run */
14534  SCIP_VAR* var, /**< problem variable */
14535  SCIP_STAT* stat, /**< problem statistics */
14536  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14537  )
14538 {
14539  assert(var != NULL);
14540  assert(stat != NULL);
14541  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14542 
14543  switch( SCIPvarGetStatus(var) )
14544  {
14546  if( var->data.original.transvar == NULL )
14547  return 0.0;
14548  else
14549  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
14550 
14551  case SCIP_VARSTATUS_LOOSE:
14552  case SCIP_VARSTATUS_COLUMN:
14553  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
14554 
14555  case SCIP_VARSTATUS_FIXED:
14556  return 0.0;
14557 
14559  if( var->data.aggregate.scalar > 0.0 )
14560  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
14561  else
14563 
14565  return 0.0;
14566 
14569 
14570  default:
14571  SCIPerrorMessage("unknown variable status\n");
14572  SCIPABORT();
14573  return 0.0; /*lint !e527*/
14574  }
14575 }
14576 
14577 /** returns the number of inferences branching on this variable in given direction triggered */
14579  SCIP_VAR* var, /**< problem variable */
14580  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14581  )
14582 {
14583  assert(var != NULL);
14584  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14585 
14586  switch( SCIPvarGetStatus(var) )
14587  {
14589  if( var->data.original.transvar == NULL )
14590  return 0.0;
14591  else
14592  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
14593 
14594  case SCIP_VARSTATUS_LOOSE:
14595  case SCIP_VARSTATUS_COLUMN:
14596  return SCIPhistoryGetInferenceSum(var->history, dir);
14597 
14598  case SCIP_VARSTATUS_FIXED:
14599  return 0.0;
14600 
14602  if( var->data.aggregate.scalar > 0.0 )
14603  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
14604  else
14606 
14608  return 0.0;
14609 
14612 
14613  default:
14614  SCIPerrorMessage("unknown variable status\n");
14615  SCIPABORT();
14616  return 0.0; /*lint !e527*/
14617  }
14618 }
14619 
14620 /** returns the number of inferences branching on this variable in given direction triggered
14621  * in the current run
14622  */
14624  SCIP_VAR* var, /**< problem variable */
14625  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14626  )
14627 {
14628  assert(var != NULL);
14629  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14630 
14631  switch( SCIPvarGetStatus(var) )
14632  {
14634  if( var->data.original.transvar == NULL )
14635  return 0.0;
14636  else
14638 
14639  case SCIP_VARSTATUS_LOOSE:
14640  case SCIP_VARSTATUS_COLUMN:
14641  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
14642 
14643  case SCIP_VARSTATUS_FIXED:
14644  return 0.0;
14645 
14647  if( var->data.aggregate.scalar > 0.0 )
14649  else
14651 
14653  return 0.0;
14654 
14657 
14658  default:
14659  SCIPerrorMessage("unknown variable status\n");
14660  SCIPABORT();
14661  return 0.0; /*lint !e527*/
14662  }
14663 }
14664 
14665 /** returns the average number of inferences found after branching on the variable in given direction */
14667  SCIP_VAR* var, /**< problem variable */
14668  SCIP_STAT* stat, /**< problem statistics */
14669  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14670  )
14671 {
14672  assert(var != NULL);
14673  assert(stat != NULL);
14674  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14675 
14676  switch( SCIPvarGetStatus(var) )
14677  {
14679  if( var->data.original.transvar == NULL )
14680  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
14681  else
14682  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
14683 
14684  case SCIP_VARSTATUS_LOOSE:
14685  case SCIP_VARSTATUS_COLUMN:
14686  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
14687  return SCIPhistoryGetAvgInferences(var->history, dir);
14688  else
14689  {
14690  int nimpls;
14691  int ncliques;
14692 
14693  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
14694  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
14695  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
14696  }
14697 
14698  case SCIP_VARSTATUS_FIXED:
14699  return 0.0;
14700 
14702  if( var->data.aggregate.scalar > 0.0 )
14703  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
14704  else
14706 
14708  return 0.0;
14709 
14711  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
14712 
14713  default:
14714  SCIPerrorMessage("unknown variable status\n");
14715  SCIPABORT();
14716  return 0.0; /*lint !e527*/
14717  }
14718 }
14719 
14720 /** returns the average number of inferences found after branching on the variable in given direction
14721  * in the current run
14722  */
14724  SCIP_VAR* var, /**< problem variable */
14725  SCIP_STAT* stat, /**< problem statistics */
14726  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14727  )
14728 {
14729  assert(var != NULL);
14730  assert(stat != NULL);
14731  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14732 
14733  switch( SCIPvarGetStatus(var) )
14734  {
14736  if( var->data.original.transvar == NULL )
14737  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
14738  else
14739  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
14740 
14741  case SCIP_VARSTATUS_LOOSE:
14742  case SCIP_VARSTATUS_COLUMN:
14743  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
14744  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
14745  else
14746  {
14747  int nimpls;
14748  int ncliques;
14749 
14750  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
14751  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
14752  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
14753  }
14754 
14755  case SCIP_VARSTATUS_FIXED:
14756  return 0.0;
14757 
14759  if( var->data.aggregate.scalar > 0.0 )
14760  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
14761  else
14763 
14765  return 0.0;
14766 
14769 
14770  default:
14771  SCIPerrorMessage("unknown variable status\n");
14772  SCIPABORT();
14773  return 0.0; /*lint !e527*/
14774  }
14775 }
14776 
14777 /** returns the number of cutoffs branching on this variable in given direction produced */
14779  SCIP_VAR* var, /**< problem variable */
14780  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14781  )
14782 {
14783  assert(var != NULL);
14784  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14785 
14786  switch( SCIPvarGetStatus(var) )
14787  {
14789  if( var->data.original.transvar == NULL )
14790  return 0;
14791  else
14792  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
14793 
14794  case SCIP_VARSTATUS_LOOSE:
14795  case SCIP_VARSTATUS_COLUMN:
14796  return SCIPhistoryGetCutoffSum(var->history, dir);
14797 
14798  case SCIP_VARSTATUS_FIXED:
14799  return 0;
14800 
14802  if( var->data.aggregate.scalar > 0.0 )
14803  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
14804  else
14806 
14808  return 0;
14809 
14812 
14813  default:
14814  SCIPerrorMessage("unknown variable status\n");
14815  SCIPABORT();
14816  return 0; /*lint !e527*/
14817  }
14818 }
14819 
14820 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
14822  SCIP_VAR* var, /**< problem variable */
14823  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14824  )
14825 {
14826  assert(var != NULL);
14827  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14828 
14829  switch( SCIPvarGetStatus(var) )
14830  {
14832  if( var->data.original.transvar == NULL )
14833  return 0;
14834  else
14836 
14837  case SCIP_VARSTATUS_LOOSE:
14838  case SCIP_VARSTATUS_COLUMN:
14839  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
14840 
14841  case SCIP_VARSTATUS_FIXED:
14842  return 0;
14843 
14845  if( var->data.aggregate.scalar > 0.0 )
14846  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
14847  else
14849 
14851  return 0;
14852 
14855 
14856  default:
14857  SCIPerrorMessage("unknown variable status\n");
14858  SCIPABORT();
14859  return 0; /*lint !e527*/
14860  }
14861 }
14862 
14863 /** returns the average number of cutoffs found after branching on the variable in given direction */
14865  SCIP_VAR* var, /**< problem variable */
14866  SCIP_STAT* stat, /**< problem statistics */
14867  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14868  )
14869 {
14870  assert(var != NULL);
14871  assert(stat != NULL);
14872  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14873 
14874  switch( SCIPvarGetStatus(var) )
14875  {
14877  if( var->data.original.transvar == NULL )
14878  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
14879  else
14880  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
14881 
14882  case SCIP_VARSTATUS_LOOSE:
14883  case SCIP_VARSTATUS_COLUMN:
14884  return SCIPhistoryGetNBranchings(var->history, dir) > 0
14885  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
14886  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
14887 
14888  case SCIP_VARSTATUS_FIXED:
14889  return 0.0;
14890 
14892  if( var->data.aggregate.scalar > 0.0 )
14893  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
14894  else
14895  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
14896 
14898  return 0.0;
14899 
14901  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
14902 
14903  default:
14904  SCIPerrorMessage("unknown variable status\n");
14905  SCIPABORT();
14906  return 0.0; /*lint !e527*/
14907  }
14908 }
14909 
14910 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
14912  SCIP_VAR* var, /**< problem variable */
14913  SCIP_STAT* stat, /**< problem statistics */
14914  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14915  )
14916 {
14917  assert(var != NULL);
14918  assert(stat != NULL);
14919  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14920 
14921  switch( SCIPvarGetStatus(var) )
14922  {
14924  if( var->data.original.transvar == NULL )
14925  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
14926  else
14927  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
14928 
14929  case SCIP_VARSTATUS_LOOSE:
14930  case SCIP_VARSTATUS_COLUMN:
14931  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
14934 
14935  case SCIP_VARSTATUS_FIXED:
14936  return 0.0;
14937 
14939  if( var->data.aggregate.scalar > 0.0 )
14940  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
14941  else
14943 
14945  return 0.0;
14946 
14949 
14950  default:
14951  SCIPerrorMessage("unknown variable status\n");
14952  SCIPABORT();
14953  return 0.0; /*lint !e527*/
14954  }
14955 }
14956 
14957 
14958 
14959 
14960 /*
14961  * information methods for bound changes
14962  */
14963 
14964 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
14966  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
14967  BMS_BLKMEM* blkmem, /**< block memory */
14968  SCIP_VAR* var, /**< active variable that changed the bounds */
14969  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
14970  SCIP_Real oldbound, /**< old value for bound */
14971  SCIP_Real newbound /**< new value for bound */
14972  )
14973 {
14974  assert(bdchginfo != NULL);
14975 
14976  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
14977  (*bdchginfo)->oldbound = oldbound;
14978  (*bdchginfo)->newbound = newbound;
14979  (*bdchginfo)->var = var;
14980  (*bdchginfo)->inferencedata.var = var;
14981  (*bdchginfo)->inferencedata.reason.prop = NULL;
14982  (*bdchginfo)->inferencedata.info = 0;
14983  (*bdchginfo)->bdchgidx.depth = INT_MAX;
14984  (*bdchginfo)->bdchgidx.pos = -1;
14985  (*bdchginfo)->pos = 0;
14986  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
14987  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
14988  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
14989  (*bdchginfo)->redundant = FALSE;
14990 
14991  return SCIP_OKAY;
14992 }
14993 
14994 /** frees a bound change information object */
14995 void SCIPbdchginfoFree(
14996  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
14997  BMS_BLKMEM* blkmem /**< block memory */
14998  )
14999 {
15000  assert(bdchginfo != NULL);
15001 
15002  BMSfreeBlockMemory(blkmem, bdchginfo);
15003 }
15004 
15005 /** returns the bound change information for the last lower bound change on given active problem variable before or
15006  * after the bound change with the given index was applied;
15007  * returns NULL, if no change to the lower bound was applied up to this point of time
15008  */
15010  SCIP_VAR* var, /**< active problem variable */
15011  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15012  SCIP_Bool after /**< should the bound change with given index be included? */
15013  )
15014 {
15015  int i;
15016 
15017  assert(var != NULL);
15018  assert(SCIPvarIsActive(var));
15019 
15020  /* search the correct bound change information for the given bound change index */
15021  if( after )
15022  {
15023  for( i = var->nlbchginfos-1; i >= 0; --i )
15024  {
15025  assert(var->lbchginfos[i].var == var);
15027  assert(var->lbchginfos[i].pos == i);
15028 
15029  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15030  if( var->lbchginfos[i].redundant )
15031  return NULL;
15032  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15033 
15034  /* if we reached the bound change index, return the current bound change info */
15035  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15036  return &var->lbchginfos[i];
15037  }
15038  }
15039  else
15040  {
15041  for( i = var->nlbchginfos-1; i >= 0; --i )
15042  {
15043  assert(var->lbchginfos[i].var == var);
15045  assert(var->lbchginfos[i].pos == i);
15046 
15047  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15048  if( var->lbchginfos[i].redundant )
15049  return NULL;
15050  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15051 
15052  /* if we reached the bound change index, return the current bound change info */
15053  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15054  return &var->lbchginfos[i];
15055  }
15056  }
15057 
15058  return NULL;
15059 }
15060 
15061 /** returns the bound change information for the last upper bound change on given active problem variable before or
15062  * after the bound change with the given index was applied;
15063  * returns NULL, if no change to the upper bound was applied up to this point of time
15064  */
15066  SCIP_VAR* var, /**< active problem variable */
15067  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15068  SCIP_Bool after /**< should the bound change with given index be included? */
15069  )
15070 {
15071  int i;
15072 
15073  assert(var != NULL);
15074  assert(SCIPvarIsActive(var));
15075 
15076  /* search the correct bound change information for the given bound change index */
15077  if( after )
15078  {
15079  for( i = var->nubchginfos-1; i >= 0; --i )
15080  {
15081  assert(var->ubchginfos[i].var == var);
15083  assert(var->ubchginfos[i].pos == i);
15084 
15085  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15086  if( var->ubchginfos[i].redundant )
15087  return NULL;
15088  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15089 
15090  /* if we reached the bound change index, return the current bound change info */
15091  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15092  return &var->ubchginfos[i];
15093  }
15094  }
15095  else
15096  {
15097  for( i = var->nubchginfos-1; i >= 0; --i )
15098  {
15099  assert(var->ubchginfos[i].var == var);
15101  assert(var->ubchginfos[i].pos == i);
15102 
15103  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15104  if( var->ubchginfos[i].redundant )
15105  return NULL;
15106  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15107 
15108  /* if we reached the bound change index, return the current bound change info */
15109  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15110  return &var->ubchginfos[i];
15111  }
15112  }
15113 
15114  return NULL;
15115 }
15116 
15117 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15118  * before or after the bound change with the given index was applied;
15119  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15120  */
15122  SCIP_VAR* var, /**< active problem variable */
15123  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15124  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15125  SCIP_Bool after /**< should the bound change with given index be included? */
15126  )
15127 {
15128  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15129  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
15130  else
15131  {
15132  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15133  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
15134  }
15135 }
15136 
15137 /** returns lower bound of variable directly before or after the bound change given by the bound change index
15138  * was applied
15139  */
15141  SCIP_VAR* var, /**< problem variable */
15142  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15143  SCIP_Bool after /**< should the bound change with given index be included? */
15144  )
15145 {
15146  SCIP_VARSTATUS varstatus;
15147  assert(var != NULL);
15148 
15149  varstatus = SCIPvarGetStatus(var);
15150 
15151  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15152  {
15153  if( bdchgidx == NULL )
15154  return SCIPvarGetLbLocal(var);
15155  else
15156  {
15157  SCIP_BDCHGINFO* bdchginfo;
15158 
15159  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
15160  if( bdchginfo != NULL )
15161  return SCIPbdchginfoGetNewbound(bdchginfo);
15162  else
15163  return var->glbdom.lb;
15164  }
15165  }
15166 
15167  /* get bounds of attached variables */
15168  switch( varstatus )
15169  {
15171  assert(var->data.original.transvar != NULL);
15172  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
15173 
15174  case SCIP_VARSTATUS_FIXED:
15175  return var->glbdom.lb;
15176 
15177  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15178  assert(var->data.aggregate.var != NULL);
15179  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15180  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15181  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15182  * (or is called by) a public interface method; instead, we only assert that values are finite
15183  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15184  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15185  */
15186  if( var->data.aggregate.scalar > 0.0 )
15187  {
15188  /* a > 0 -> get lower bound of y */
15189  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15190  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15191  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15192  + var->data.aggregate.constant;
15193  }
15194  else if( var->data.aggregate.scalar < 0.0 )
15195  {
15196  /* a < 0 -> get upper bound of y */
15197  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15198  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15199  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15200  + var->data.aggregate.constant;
15201  }
15202  else
15203  {
15204  SCIPerrorMessage("scalar is zero in aggregation\n");
15205  SCIPABORT();
15206  return SCIP_INVALID; /*lint !e527*/
15207  }
15208 
15210  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
15211  SCIPABORT();
15212  return SCIP_INVALID; /*lint !e527*/
15213 
15214  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15215  assert(var->negatedvar != NULL);
15217  assert(var->negatedvar->negatedvar == var);
15218  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
15219 
15220  case SCIP_VARSTATUS_COLUMN: /* for lint */
15221  case SCIP_VARSTATUS_LOOSE: /* for lint */
15222  default:
15223  SCIPerrorMessage("unknown variable status\n");
15224  SCIPABORT();
15225  return SCIP_INVALID; /*lint !e527*/
15226  }
15227 }
15228 
15229 /** returns upper bound of variable directly before or after the bound change given by the bound change index
15230  * was applied
15231  */
15233  SCIP_VAR* var, /**< problem variable */
15234  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15235  SCIP_Bool after /**< should the bound change with given index be included? */
15236  )
15237 {
15238  SCIP_VARSTATUS varstatus;
15239  assert(var != NULL);
15240 
15241  varstatus = SCIPvarGetStatus(var);
15242 
15243  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15244  {
15245  if( bdchgidx == NULL )
15246  return SCIPvarGetUbLocal(var);
15247  else
15248  {
15249  SCIP_BDCHGINFO* bdchginfo;
15250 
15251  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
15252  if( bdchginfo != NULL )
15253  return SCIPbdchginfoGetNewbound(bdchginfo);
15254  else
15255  return var->glbdom.ub;
15256  }
15257  }
15258 
15259  /* get bounds of attached variables */
15260  switch( varstatus )
15261  {
15263  assert(var->data.original.transvar != NULL);
15264  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
15265 
15266  case SCIP_VARSTATUS_FIXED:
15267  return var->glbdom.ub;
15268 
15269  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15270  assert(var->data.aggregate.var != NULL);
15271  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15272  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15273  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15274  * (or is called by) a public interface method; instead, we only assert that values are finite
15275  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15276  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15277  */
15278  if( var->data.aggregate.scalar > 0.0 )
15279  {
15280  /* a > 0 -> get lower bound of y */
15281  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15282  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15283  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15284  + var->data.aggregate.constant;
15285  }
15286  else if( var->data.aggregate.scalar < 0.0 )
15287  {
15288  /* a < 0 -> get upper bound of y */
15289  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15290  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15291  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15292  + var->data.aggregate.constant;
15293  }
15294  else
15295  {
15296  SCIPerrorMessage("scalar is zero in aggregation\n");
15297  SCIPABORT();
15298  return SCIP_INVALID; /*lint !e527*/
15299  }
15300 
15302  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
15303  SCIPABORT();
15304  return SCIP_INVALID; /*lint !e527*/
15305 
15306  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15307  assert(var->negatedvar != NULL);
15309  assert(var->negatedvar->negatedvar == var);
15310  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
15311 
15312  case SCIP_VARSTATUS_COLUMN: /* for lint */
15313  case SCIP_VARSTATUS_LOOSE: /* for lint */
15314  default:
15315  SCIPerrorMessage("unknown variable status\n");
15316  SCIPABORT();
15317  return SCIP_INVALID; /*lint !e527*/
15318  }
15319 }
15320 
15321 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
15322  * was applied
15323  */
15325  SCIP_VAR* var, /**< problem variable */
15326  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15327  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15328  SCIP_Bool after /**< should the bound change with given index be included? */
15329  )
15330 {
15331  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15332  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
15333  else
15334  {
15335  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15336  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
15337  }
15338 }
15339 
15340 /** returns whether the binary variable was fixed at the time given by the bound change index */
15342  SCIP_VAR* var, /**< problem variable */
15343  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15344  SCIP_Bool after /**< should the bound change with given index be included? */
15345  )
15346 {
15347  assert(var != NULL);
15348  assert(SCIPvarIsBinary(var));
15349 
15350  /* check the current bounds first in order to decide at which bound change information we have to look
15351  * (which is expensive because we have to follow the aggregation tree to the active variable)
15352  */
15353  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
15354  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
15355 }
15356 
15357 /** bound change index representing the initial time before any bound changes took place */
15358 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
15360 /** bound change index representing the presolving stage */
15361 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
15363 /** returns the last bound change index, at which the bounds of the given variable were tightened */
15365  SCIP_VAR* var /**< problem variable */
15366  )
15367 {
15368  SCIP_BDCHGIDX* lbchgidx;
15369  SCIP_BDCHGIDX* ubchgidx;
15370 
15371  assert(var != NULL);
15372 
15373  var = SCIPvarGetProbvar(var);
15374 
15375  /* check, if variable is original without transformed variable */
15376  if( var == NULL )
15377  return &initbdchgidx;
15378 
15379  /* check, if variable was fixed in presolving */
15380  if( !SCIPvarIsActive(var) )
15381  return &presolvebdchgidx;
15382 
15384 
15385  /* get depths of last bound change information for the lower and upper bound */
15386  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
15387  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
15388  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
15389  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
15390 
15391  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
15392  return ubchgidx;
15393  else
15394  return lbchgidx;
15395 }
15396 
15397 /** returns the last depth level, at which the bounds of the given variable were tightened;
15398  * returns -2, if the variable's bounds are still the global bounds
15399  * returns -1, if the variable was fixed in presolving
15400  */
15402  SCIP_VAR* var /**< problem variable */
15403  )
15404 {
15405  SCIP_BDCHGIDX* bdchgidx;
15406 
15407  bdchgidx = SCIPvarGetLastBdchgIndex(var);
15408  assert(bdchgidx != NULL);
15409 
15410  return bdchgidx->depth;
15411 }
15412 
15413 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
15414  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
15415  */
15417  SCIP_VAR* var, /**< problem variable */
15418  SCIP_SET* set, /**< global SCIP settings */
15419  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
15420  SCIP_Real bound /**< conflicting bound */
15421  )
15422 {
15423  int i;
15424 
15425  assert(var != NULL);
15426  assert(set != NULL);
15427  assert(var->scip == set->scip);
15428 
15429  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15430  {
15431  /* check if the bound is in conflict with the current local bounds */
15432  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
15433  return -1;
15434 
15435  /* check if the bound is in conflict with the global bound */
15436  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
15437  return 0;
15438 
15439  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
15440  assert(var->nubchginfos > 0);
15441  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
15442 
15443  /* search for the first conflicting bound change */
15444  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
15445  {
15446  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
15448  }
15449  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
15450  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
15451 
15452  /* return the depth at which the first conflicting bound change took place */
15453  return var->ubchginfos[i].bdchgidx.depth;
15454  }
15455  else
15456  {
15457  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15458 
15459  /* check if the bound is in conflict with the current local bounds */
15460  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
15461  return -1;
15462 
15463  /* check if the bound is in conflict with the global bound */
15464  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
15465  return 0;
15466 
15467  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
15468  assert(var->nlbchginfos > 0);
15469  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
15470 
15471  /* search for the first conflicting bound change */
15472  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
15473  {
15474  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
15476  }
15477  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
15478  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
15479 
15480  /* return the depth at which the first conflicting bound change took place */
15481  return var->lbchginfos[i].bdchgidx.depth;
15482  }
15483 }
15484 
15485 /** returns whether the first binary variable was fixed earlier than the second one;
15486  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
15487  * second one is not fixed
15488  */
15490  SCIP_VAR* var1, /**< first binary variable */
15491  SCIP_VAR* var2 /**< second binary variable */
15492  )
15493 {
15494  SCIP_BDCHGIDX* bdchgidx1;
15495  SCIP_BDCHGIDX* bdchgidx2;
15496 
15497  assert(var1 != NULL);
15498  assert(var2 != NULL);
15499  assert(SCIPvarIsBinary(var1));
15500  assert(SCIPvarIsBinary(var2));
15501 
15502  var1 = SCIPvarGetProbvar(var1);
15503  var2 = SCIPvarGetProbvar(var2);
15504  assert(var1 != NULL);
15505  assert(var2 != NULL);
15506 
15507  /* check, if variables are globally fixed */
15508  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
15509  return FALSE;
15510  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
15511  return TRUE;
15512 
15515  assert(SCIPvarIsBinary(var1));
15516  assert(SCIPvarIsBinary(var2));
15517  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
15518  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
15519  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
15520  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
15521  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
15522  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
15523 
15524  if( var1->nlbchginfos == 1 )
15525  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
15526  else if( var1->nubchginfos == 1 )
15527  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
15528  else
15529  bdchgidx1 = NULL;
15530 
15531  if( var2->nlbchginfos == 1 )
15532  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
15533  else if( var2->nubchginfos == 1 )
15534  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
15535  else
15536  bdchgidx2 = NULL;
15537 
15538  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
15539 }
15540 
15541 
15542 
15543 /*
15544  * Hash functions
15545  */
15546 
15547 /** gets the key (i.e. the name) of the given variable */
15548 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
15549 { /*lint --e{715}*/
15550  SCIP_VAR* var = (SCIP_VAR*)elem;
15551 
15552  assert(var != NULL);
15553  return var->name;
15554 }
15555 
15556 
15557 
15558 
15559 /*
15560  * simple functions implemented as defines
15561  */
15562 
15563 /* In debug mode, the following methods are implemented as function calls to ensure
15564  * type validity.
15565  * In optimized mode, the methods are implemented as defines to improve performance.
15566  * However, we want to have them in the library anyways, so we have to undef the defines.
15567  */
15568 
15569 #undef SCIPboundchgGetNewbound
15570 #undef SCIPboundchgGetVar
15571 #undef SCIPboundchgGetBoundchgtype
15572 #undef SCIPboundchgGetBoundtype
15573 #undef SCIPboundchgIsRedundant
15574 #undef SCIPdomchgGetNBoundchgs
15575 #undef SCIPdomchgGetBoundchg
15576 #undef SCIPholelistGetLeft
15577 #undef SCIPholelistGetRight
15578 #undef SCIPholelistGetNext
15579 #undef SCIPvarGetName
15580 #undef SCIPvarGetNUses
15581 #undef SCIPvarGetData
15582 #undef SCIPvarSetData
15583 #undef SCIPvarSetDelorigData
15584 #undef SCIPvarSetTransData
15585 #undef SCIPvarSetDeltransData
15586 #undef SCIPvarGetStatus
15587 #undef SCIPvarIsOriginal
15588 #undef SCIPvarIsTransformed
15589 #undef SCIPvarIsNegated
15590 #undef SCIPvarGetType
15591 #undef SCIPvarIsBinary
15592 #undef SCIPvarIsIntegral
15593 #undef SCIPvarIsInitial
15594 #undef SCIPvarIsRemovable
15595 #undef SCIPvarIsDeleted
15596 #undef SCIPvarIsDeletable
15597 #undef SCIPvarMarkDeletable
15598 #undef SCIPvarMarkNotDeletable
15599 #undef SCIPvarIsActive
15600 #undef SCIPvarGetIndex
15601 #undef SCIPvarGetProbindex
15602 #undef SCIPvarGetTransVar
15603 #undef SCIPvarGetCol
15604 #undef SCIPvarIsInLP
15605 #undef SCIPvarGetAggrVar
15606 #undef SCIPvarGetAggrScalar
15607 #undef SCIPvarGetAggrConstant
15608 #undef SCIPvarGetMultaggrNVars
15609 #undef SCIPvarGetMultaggrVars
15610 #undef SCIPvarGetMultaggrScalars
15611 #undef SCIPvarGetMultaggrConstant
15612 #undef SCIPvarGetNegatedVar
15613 #undef SCIPvarGetNegationVar
15614 #undef SCIPvarGetNegationConstant
15615 #undef SCIPvarGetObj
15616 #undef SCIPvarGetLbOriginal
15617 #undef SCIPvarGetUbOriginal
15618 #undef SCIPvarGetHolelistOriginal
15619 #undef SCIPvarGetLbGlobal
15620 #undef SCIPvarGetUbGlobal
15621 #undef SCIPvarGetHolelistGlobal
15622 #undef SCIPvarGetBestBoundGlobal
15623 #undef SCIPvarGetWorstBoundGlobal
15624 #undef SCIPvarGetLbLocal
15625 #undef SCIPvarGetUbLocal
15626 #undef SCIPvarGetHolelistLocal
15627 #undef SCIPvarGetBestBoundLocal
15628 #undef SCIPvarGetWorstBoundLocal
15629 #undef SCIPvarGetBestBoundType
15630 #undef SCIPvarGetWorstBoundType
15631 #undef SCIPvarGetLbLazy
15632 #undef SCIPvarGetUbLazy
15633 #undef SCIPvarGetBranchFactor
15634 #undef SCIPvarGetBranchPriority
15635 #undef SCIPvarGetBranchDirection
15636 #undef SCIPvarGetNVlbs
15637 #undef SCIPvarGetVlbVars
15638 #undef SCIPvarGetVlbCoefs
15639 #undef SCIPvarGetVlbConstants
15640 #undef SCIPvarGetNVubs
15641 #undef SCIPvarGetVubVars
15642 #undef SCIPvarGetVubCoefs
15643 #undef SCIPvarGetVubConstants
15644 #undef SCIPvarGetNImpls
15645 #undef SCIPvarGetNBinImpls
15646 #undef SCIPvarGetImplVars
15647 #undef SCIPvarGetImplTypes
15648 #undef SCIPvarGetImplBounds
15649 #undef SCIPvarGetImplIds
15650 #undef SCIPvarGetNCliques
15651 #undef SCIPvarGetCliques
15652 #undef SCIPvarGetLPSol
15653 #undef SCIPvarGetNLPSol
15654 #undef SCIPvarGetBdchgInfoLb
15655 #undef SCIPvarGetNBdchgInfosLb
15656 #undef SCIPvarGetBdchgInfoUb
15657 #undef SCIPvarGetNBdchgInfosUb
15658 #undef SCIPvarGetValuehistory
15659 #undef SCIPvarGetPseudoSol
15660 #undef SCIPvarCatchEvent
15661 #undef SCIPvarDropEvent
15662 #undef SCIPvarGetVSIDS
15663 #undef SCIPbdchgidxGetPos
15664 #undef SCIPbdchgidxIsEarlierNonNull
15665 #undef SCIPbdchgidxIsEarlier
15666 #undef SCIPbdchginfoGetOldbound
15667 #undef SCIPbdchginfoGetNewbound
15668 #undef SCIPbdchginfoGetVar
15669 #undef SCIPbdchginfoGetChgtype
15670 #undef SCIPbdchginfoGetBoundtype
15671 #undef SCIPbdchginfoGetDepth
15672 #undef SCIPbdchginfoGetPos
15673 #undef SCIPbdchginfoGetIdx
15674 #undef SCIPbdchginfoGetInferVar
15675 #undef SCIPbdchginfoGetInferCons
15676 #undef SCIPbdchginfoGetInferProp
15677 #undef SCIPbdchginfoGetInferInfo
15678 #undef SCIPbdchginfoGetInferBoundtype
15679 #undef SCIPbdchginfoIsRedundant
15680 #undef SCIPbdchginfoHasInferenceReason
15681 #undef SCIPbdchginfoIsTighter
15682 
15683 /** returns the new value of the bound in the bound change data */
15685  SCIP_BOUNDCHG* boundchg /**< bound change data */
15686  )
15687 {
15688  assert(boundchg != NULL);
15689 
15690  return boundchg->newbound;
15691 }
15692 
15693 /** returns the variable of the bound change in the bound change data */
15695  SCIP_BOUNDCHG* boundchg /**< bound change data */
15696  )
15697 {
15698  assert(boundchg != NULL);
15699 
15700  return boundchg->var;
15701 }
15702 
15703 /** returns the bound change type of the bound change in the bound change data */
15705  SCIP_BOUNDCHG* boundchg /**< bound change data */
15706  )
15707 {
15708  assert(boundchg != NULL);
15709 
15710  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
15711 }
15712 
15713 /** returns the bound type of the bound change in the bound change data */
15715  SCIP_BOUNDCHG* boundchg /**< bound change data */
15716  )
15717 {
15718  assert(boundchg != NULL);
15719 
15720  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
15721 }
15722 
15723 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
15725  SCIP_BOUNDCHG* boundchg /**< bound change data */
15726  )
15727 {
15728  assert(boundchg != NULL);
15729 
15730  return boundchg->redundant;
15731 }
15732 
15733 /** returns the number of bound changes in the domain change data */
15735  SCIP_DOMCHG* domchg /**< domain change data */
15736  )
15737 {
15738  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
15739 }
15740 
15741 /** returns a particular bound change in the domain change data */
15743  SCIP_DOMCHG* domchg, /**< domain change data */
15744  int pos /**< position of the bound change in the domain change data */
15745  )
15746 {
15747  assert(domchg != NULL);
15748  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
15749 
15750  return &domchg->domchgbound.boundchgs[pos];
15751 }
15752 
15753 /** returns left bound of open interval in hole */
15755  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
15756  )
15757 {
15758  assert(holelist != NULL);
15759 
15760  return holelist->hole.left;
15761 }
15762 
15763 /** returns right bound of open interval in hole */
15765  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
15766  )
15767 {
15768  assert(holelist != NULL);
15769 
15770  return holelist->hole.right;
15771 }
15772 
15773 /** returns next hole in list */
15775  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
15776  )
15777 {
15778  assert(holelist != NULL);
15779 
15780  return holelist->next;
15781 }
15782 
15783 /** returns the name of the variable
15784  *
15785  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
15786  */
15787 const char* SCIPvarGetName(
15788  SCIP_VAR* var /**< problem variable */
15789  )
15790 {
15791  assert(var != NULL);
15792 
15793  return var->name;
15794 }
15795 
15796 /** gets number of times, the variable is currently captured */
15797 int SCIPvarGetNUses(
15798  SCIP_VAR* var /**< problem variable */
15799  )
15800 {
15801  assert(var != NULL);
15802 
15803  return var->nuses;
15804 }
15805 
15806 /** returns the user data of the variable */
15808  SCIP_VAR* var /**< problem variable */
15809  )
15810 {
15811  assert(var != NULL);
15812 
15813  return var->vardata;
15814 }
15815 
15816 /** sets the user data for the variable */
15817 void SCIPvarSetData(
15818  SCIP_VAR* var, /**< problem variable */
15819  SCIP_VARDATA* vardata /**< user variable data */
15820  )
15821 {
15822  assert(var != NULL);
15823 
15824  var->vardata = vardata;
15825 }
15826 
15827 /** sets method to free user data for the original variable */
15829  SCIP_VAR* var, /**< problem variable */
15830  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
15831  )
15832 {
15833  assert(var != NULL);
15834  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
15835 
15836  var->vardelorig = vardelorig;
15837 }
15838 
15839 /** sets method to transform user data of the variable */
15840 void SCIPvarSetTransData(
15841  SCIP_VAR* var, /**< problem variable */
15842  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
15843  )
15844 {
15845  assert(var != NULL);
15846  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
15847 
15848  var->vartrans = vartrans;
15849 }
15850 
15851 /** sets method to free transformed user data for the variable */
15853  SCIP_VAR* var, /**< problem variable */
15854  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
15855  )
15856 {
15857  assert(var != NULL);
15858 
15859  var->vardeltrans = vardeltrans;
15860 }
15861 
15862 /** sets method to copy this variable into sub-SCIPs */
15863 void SCIPvarSetCopyData(
15864  SCIP_VAR* var, /**< problem variable */
15865  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
15866  )
15867 {
15868  assert(var != NULL);
15869 
15870  var->varcopy = varcopy;
15871 }
15872 
15873 /** sets the initial flag of a variable; only possible for original or loose variables */
15875  SCIP_VAR* var, /**< problem variable */
15876  SCIP_Bool initial /**< initial flag */
15877  )
15878 {
15879  assert(var != NULL);
15880 
15882  return SCIP_INVALIDCALL;
15883 
15884  var->initial = initial;
15885 
15886  return SCIP_OKAY;
15887 }
15888 
15889 /** sets the removable flag of a variable; only possible for original or loose variables */
15891  SCIP_VAR* var, /**< problem variable */
15892  SCIP_Bool removable /**< removable flag */
15893  )
15894 {
15895  assert(var != NULL);
15896 
15898  return SCIP_INVALIDCALL;
15899 
15900  var->removable = removable;
15901 
15902  return SCIP_OKAY;
15903 }
15904 
15905 /** gets status of variable */
15907  SCIP_VAR* var /**< problem variable */
15908  )
15909 {
15910  assert(var != NULL);
15911 
15912  return (SCIP_VARSTATUS)(var->varstatus);
15913 }
15914 
15915 /** returns whether the variable belongs to the original problem */
15917  SCIP_VAR* var /**< problem variable */
15918  )
15919 {
15920  assert(var != NULL);
15921  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
15922 
15926 }
15927 
15928 /** returns whether the variable belongs to the transformed problem */
15930  SCIP_VAR* var /**< problem variable */
15931  )
15932 {
15933  assert(var != NULL);
15934  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
15935 
15939 }
15940 
15941 /** returns whether the variable was created by negation of a different variable */
15943  SCIP_VAR* var /**< problem variable */
15944  )
15945 {
15946  assert(var != NULL);
15947 
15948  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
15949 }
15950 
15951 /** gets type of variable */
15953  SCIP_VAR* var /**< problem variable */
15954  )
15955 {
15956  assert(var != NULL);
15957 
15958  return (SCIP_VARTYPE)(var->vartype);
15959 }
15960 
15961 /** returns TRUE if the variable is of binary type; this is the case if:
15962  * (1) variable type is binary
15963  * (2) variable type is integer or implicit integer and
15964  * (i) the lazy lower bound or the global lower bound is greater or equal to zero
15965  * (ii) the lazy upper bound or the global upper bound is less tor equal to one
15966  */
15968  SCIP_VAR* var /**< problem variable */
15969  )
15970 {
15971  assert(var != NULL);
15972 
15973  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
15974  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
15975 }
15976 
15977 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
15979  SCIP_VAR* var /**< problem variable */
15980  )
15981 {
15982  assert(var != NULL);
15983 
15984  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
15985 }
15986 
15987 /** returns whether variable's column should be present in the initial root LP */
15989  SCIP_VAR* var /**< problem variable */
15990  )
15991 {
15992  assert(var != NULL);
15993 
15994  return var->initial;
15995 }
15996 
15997 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
15999  SCIP_VAR* var /**< problem variable */
16000  )
16001 {
16002  assert(var != NULL);
16003 
16004  return var->removable;
16005 }
16006 
16007 /** returns whether the variable was deleted from the problem */
16009  SCIP_VAR* var /**< problem variable */
16010  )
16011 {
16012  assert(var != NULL);
16013 
16014  return var->deleted;
16015 }
16016 
16017 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16018  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16019  */
16021  SCIP_VAR* var /**< problem variable */
16022  )
16023 {
16024  assert(var != NULL);
16025  assert(var->probindex == -1);
16026 
16027  var->deletable = TRUE;
16028 }
16029 
16030 /** marks the variable to be not deletable from the problem */
16033  )
16034 {
16035  assert(var != NULL);
16036 
16037  var->deletable = FALSE;
16038 }
16039 
16040 /** returns whether variable is allowed to be deleted completely from the problem */
16043  )
16044 {
16045  assert(var != NULL);
16046 
16047  return var->deletable;
16048 }
16049 
16050 /** returns whether variable is an active (neither fixed nor aggregated) variable */
16052  SCIP_VAR* var /**< problem variable */
16053  )
16054 {
16055  assert(var != NULL);
16056 
16057  return (var->probindex >= 0);
16058 }
16059 
16060 /** gets unique index of variable */
16061 int SCIPvarGetIndex(
16062  SCIP_VAR* var /**< problem variable */
16063  )
16064 {
16065  assert(var != NULL);
16066 
16067  return var->index;
16068 }
16069 
16070 /** gets position of variable in problem, or -1 if variable is not active */
16072  SCIP_VAR* var /**< problem variable */
16073  )
16074 {
16075  assert(var != NULL);
16076 
16077  return var->probindex;
16078 }
16079 
16080 /** gets transformed variable of ORIGINAL variable */
16082  SCIP_VAR* var /**< problem variable */
16083  )
16084 {
16085  assert(var != NULL);
16086  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16087 
16088  return var->data.original.transvar;
16089 }
16090 
16091 /** gets column of COLUMN variable */
16093  SCIP_VAR* var /**< problem variable */
16094  )
16095 {
16096  assert(var != NULL);
16097  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16098 
16099  return var->data.col;
16100 }
16101 
16102 /** returns whether the variable is a COLUMN variable that is member of the current LP */
16104  SCIP_VAR* var /**< problem variable */
16105  )
16106 {
16107  assert(var != NULL);
16108 
16109  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
16110 }
16111 
16112 /** gets aggregation variable y of an aggregated variable x = a*y + c */
16114  SCIP_VAR* var /**< problem variable */
16115  )
16116 {
16117  assert(var != NULL);
16119 
16120  return var->data.aggregate.var;
16121 }
16122 
16123 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
16125  SCIP_VAR* var /**< problem variable */
16126  )
16127 {
16128  assert(var != NULL);
16130 
16131  return var->data.aggregate.scalar;
16132 }
16133 
16134 /** gets aggregation constant c of an aggregated variable x = a*y + c */
16136  SCIP_VAR* var /**< problem variable */
16137  )
16138 {
16139  assert(var != NULL);
16141 
16142  return var->data.aggregate.constant;
16143 }
16144 
16145 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16147  SCIP_VAR* var /**< problem variable */
16148  )
16149 {
16150  assert(var != NULL);
16151  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16152  assert(!var->donotmultaggr);
16153 
16154  return var->data.multaggr.nvars;
16155 }
16156 
16157 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16159  SCIP_VAR* var /**< problem variable */
16160  )
16161 {
16162  assert(var != NULL);
16163  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16164  assert(!var->donotmultaggr);
16165 
16166  return var->data.multaggr.vars;
16167 }
16168 
16169 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16171  SCIP_VAR* var /**< problem variable */
16172  )
16173 {
16174  assert(var != NULL);
16175  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16176  assert(!var->donotmultaggr);
16177 
16178  return var->data.multaggr.scalars;
16179 }
16180 
16181 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16183  SCIP_VAR* var /**< problem variable */
16184  )
16185 {
16186  assert(var != NULL);
16187  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16188  assert(!var->donotmultaggr);
16189 
16190  return var->data.multaggr.constant;
16191 }
16192 
16193 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
16195  SCIP_VAR* var /**< negated problem variable */
16196  )
16197 {
16198  assert(var != NULL);
16199 
16200  return var->negatedvar;
16201 }
16202 
16203 /** gets the negation variable x of a negated variable x' = offset - x */
16205  SCIP_VAR* var /**< negated problem variable */
16206  )
16207 {
16208  assert(var != NULL);
16209  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16210 
16211  return var->negatedvar;
16212 }
16213 
16214 /** gets the negation offset of a negated variable x' = offset - x */
16216  SCIP_VAR* var /**< negated problem variable */
16217  )
16218 {
16219  assert(var != NULL);
16220  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16221 
16222  return var->data.negate.constant;
16223 }
16224 
16225 /** gets objective function value of variable */
16227  SCIP_VAR* var /**< problem variable */
16228  )
16229 {
16230  assert(var != NULL);
16231 
16232  return var->obj;
16233 }
16234 
16235 
16236 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
16237  * e.g. obj(x) = 1 this method returns for ~x the value -1
16238  */
16240  SCIP_VAR* var, /**< problem variable */
16241  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
16242  )
16243 {
16244  SCIP_VAR* probvar = var;
16245  SCIP_Real mult = 1.0;
16246 
16247  assert(probvar != NULL);
16248  assert(aggrobj != NULL);
16249 
16250  while( probvar != NULL )
16251  {
16252  switch( SCIPvarGetStatus(probvar) )
16253  {
16255  case SCIP_VARSTATUS_LOOSE:
16256  case SCIP_VARSTATUS_COLUMN:
16257  (*aggrobj) = mult * SCIPvarGetObj(probvar);
16258  return SCIP_OKAY;
16259 
16260  case SCIP_VARSTATUS_FIXED:
16261  assert(SCIPvarGetObj(probvar) == 0.0);
16262  (*aggrobj) = 0.0;
16263  return SCIP_OKAY;
16264 
16266  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16267  if ( probvar->data.multaggr.nvars == 1 )
16268  {
16269  assert( probvar->data.multaggr.vars != NULL );
16270  assert( probvar->data.multaggr.scalars != NULL );
16271  assert( probvar->data.multaggr.vars[0] != NULL );
16272  mult *= probvar->data.multaggr.scalars[0];
16273  probvar = probvar->data.multaggr.vars[0];
16274  break;
16275  }
16276  else
16277  {
16278  SCIP_Real tmpobj;
16279  int v;
16280 
16281  (*aggrobj) = 0.0;
16282 
16283  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
16284  {
16285  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
16286  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
16287  }
16288  return SCIP_OKAY;
16289  }
16290 
16291  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
16292  assert(probvar->data.aggregate.var != NULL);
16293  mult *= probvar->data.aggregate.scalar;
16294  probvar = probvar->data.aggregate.var;
16295  break;
16296 
16297  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
16298  assert(probvar->negatedvar != NULL);
16299  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
16300  assert(probvar->negatedvar->negatedvar == probvar);
16301  mult *= -1.0;
16302  probvar = probvar->negatedvar;
16303  break;
16304 
16305  default:
16306  SCIPABORT();
16307  return SCIP_INVALIDDATA; /*lint !e527*/
16308  }
16309  }
16310 
16311  return SCIP_INVALIDDATA;
16312 }
16313 
16314 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
16316  SCIP_VAR* var /**< original problem variable */
16317  )
16318 {
16319  assert(var != NULL);
16320  assert(SCIPvarIsOriginal(var));
16321 
16323  return var->data.original.origdom.lb;
16324  else
16325  {
16326  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16327  assert(var->negatedvar != NULL);
16329 
16330  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
16331  }
16332 }
16333 
16334 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
16336  SCIP_VAR* var /**< original problem variable */
16337  )
16338 {
16339  assert(var != NULL);
16340  assert(SCIPvarIsOriginal(var));
16341 
16343  return var->data.original.origdom.ub;
16344  else
16345  {
16346  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16347  assert(var->negatedvar != NULL);
16349 
16350  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
16351  }
16352 }
16353 
16354 /** gets the original hole list of an original variable */
16356  SCIP_VAR* var /**< problem variable */
16357  )
16358 {
16359  assert(var != NULL);
16360  assert(SCIPvarIsOriginal(var));
16361 
16363  return var->data.original.origdom.holelist;
16364 
16365  return NULL;
16366 }
16367 
16368 /** gets global lower bound of variable */
16370  SCIP_VAR* var /**< problem variable */
16371  )
16372 {
16373  assert(var != NULL);
16374 
16375  return var->glbdom.lb;
16376 }
16377 
16378 /** gets global upper bound of variable */
16380  SCIP_VAR* var /**< problem variable */
16381  )
16382 {
16383  assert(var != NULL);
16384 
16385  return var->glbdom.ub;
16386 }
16387 
16388 /** gets the global hole list of an active variable */
16390  SCIP_VAR* var /**< problem variable */
16391  )
16392 {
16393  assert(var != NULL);
16394 
16395  return var->glbdom.holelist;
16396 }
16397 
16398 /** gets best global bound of variable with respect to the objective function */
16400  SCIP_VAR* var /**< problem variable */
16401  )
16402 {
16403  assert(var != NULL);
16404 
16405  if( var->obj >= 0.0 )
16406  return var->glbdom.lb;
16407  else
16408  return var->glbdom.ub;
16409 }
16410 
16411 /** gets worst global bound of variable with respect to the objective function */
16413  SCIP_VAR* var /**< problem variable */
16414  )
16415 {
16416  assert(var != NULL);
16417 
16418  if( var->obj >= 0.0 )
16419  return var->glbdom.ub;
16420  else
16421  return var->glbdom.lb;
16422 }
16423 
16424 /** gets current lower bound of variable */
16426  SCIP_VAR* var /**< problem variable */
16427  )
16428 {
16429  assert(var != NULL);
16430 
16431  return var->locdom.lb;
16432 }
16433 
16434 /** gets current upper bound of variable */
16436  SCIP_VAR* var /**< problem variable */
16437  )
16438 {
16439  assert(var != NULL);
16440 
16441  return var->locdom.ub;
16442 }
16443 
16444 /** gets the current hole list of an active variable */
16446  SCIP_VAR* var /**< problem variable */
16447  )
16448 {
16449  assert(var != NULL);
16450 
16451  return var->locdom.holelist;
16452 }
16453 
16454 /** gets best local bound of variable with respect to the objective function */
16456  SCIP_VAR* var /**< problem variable */
16457  )
16458 {
16459  assert(var != NULL);
16460 
16461  if( var->obj >= 0.0 )
16462  return var->locdom.lb;
16463  else
16464  return var->locdom.ub;
16465 }
16466 
16467 /** gets worst local bound of variable with respect to the objective function */
16469  SCIP_VAR* var /**< problem variable */
16470  )
16471 {
16472  assert(var != NULL);
16473 
16474  if( var->obj >= 0.0 )
16475  return var->locdom.ub;
16476  else
16477  return var->locdom.lb;
16478 }
16479 
16480 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
16482  SCIP_VAR* var /**< problem variable */
16483  )
16484 {
16485  assert(var != NULL);
16486 
16487  if( var->obj >= 0.0 )
16488  return SCIP_BOUNDTYPE_LOWER;
16489  else
16490  return SCIP_BOUNDTYPE_UPPER;
16491 }
16492 
16493 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
16495  SCIP_VAR* var /**< problem variable */
16496  )
16497 {
16498  assert(var != NULL);
16499 
16500  if( var->obj >= 0.0 )
16501  return SCIP_BOUNDTYPE_UPPER;
16502  else
16503  return SCIP_BOUNDTYPE_LOWER;
16504 }
16505 
16506 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
16508  SCIP_VAR* var /**< problem variable */
16509  )
16510 {
16511  assert(var != NULL);
16512 
16513  return var->lazylb;
16514 }
16515 
16516 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
16518  SCIP_VAR* var /**< problem variable */
16519  )
16520 {
16521  assert(var != NULL);
16522 
16523  return var->lazyub;
16524 }
16525 
16526 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
16527  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
16528  */
16530  SCIP_VAR* var /**< problem variable */
16531  )
16532 {
16533  assert(var != NULL);
16534 
16535  return var->branchfactor;
16536 }
16537 
16538 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
16539  * with lower priority
16540  */
16542  SCIP_VAR* var /**< problem variable */
16543  )
16544 {
16545  assert(var != NULL);
16546 
16547  return var->branchpriority;
16548 }
16549 
16550 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
16552  SCIP_VAR* var /**< problem variable */
16553  )
16554 {
16555  assert(var != NULL);
16556 
16557  return (SCIP_BRANCHDIR)var->branchdirection;
16558 }
16559 
16560 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
16561 int SCIPvarGetNVlbs(
16562  SCIP_VAR* var /**< problem variable */
16563  )
16564 {
16565  assert(var != NULL);
16566 
16567  return SCIPvboundsGetNVbds(var->vlbs);
16568 }
16569 
16570 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
16571  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
16572  */
16574  SCIP_VAR* var /**< problem variable */
16575  )
16576 {
16577  assert(var != NULL);
16578 
16579  return SCIPvboundsGetVars(var->vlbs);
16580 }
16581 
16582 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
16584  SCIP_VAR* var /**< problem variable */
16585  )
16586 {
16587  assert(var != NULL);
16588 
16589  return SCIPvboundsGetCoefs(var->vlbs);
16590 }
16591 
16592 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
16594  SCIP_VAR* var /**< problem variable */
16595  )
16596 {
16597  assert(var != NULL);
16598 
16599  return SCIPvboundsGetConstants(var->vlbs);
16600 }
16601 
16602 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
16603 int SCIPvarGetNVubs(
16604  SCIP_VAR* var /**< problem variable */
16605  )
16606 {
16607  assert(var != NULL);
16608 
16609  return SCIPvboundsGetNVbds(var->vubs);
16610 }
16611 
16612 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
16613  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
16614  */
16616  SCIP_VAR* var /**< problem variable */
16617  )
16618 {
16619  assert(var != NULL);
16620 
16621  return SCIPvboundsGetVars(var->vubs);
16622 }
16623 
16624 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
16626  SCIP_VAR* var /**< problem variable */
16627  )
16628 {
16629  assert(var != NULL);
16630 
16631  return SCIPvboundsGetCoefs(var->vubs);
16632 }
16633 
16634 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
16636  SCIP_VAR* var /**< problem variable */
16637  )
16638 {
16639  assert(var != NULL);
16640 
16641  return SCIPvboundsGetConstants(var->vubs);
16642 }
16643 
16644 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
16645  * there are no implications for nonbinary variable x
16646  */
16647 int SCIPvarGetNImpls(
16648  SCIP_VAR* var, /**< active problem variable */
16649  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16650  )
16651 {
16652  assert(var != NULL);
16653  assert(SCIPvarIsActive(var));
16654 
16655  return SCIPimplicsGetNImpls(var->implics, varfixing);
16656 }
16657 
16658 /** gets number of implications y <= 0 or y >= 1 for x == 0 or x == 1 of given active problem variable x with binary y,
16659  * there are no implications for nonbinary variable x
16660  */
16662  SCIP_VAR* var, /**< active problem variable */
16663  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16664  )
16665 {
16666  assert(var != NULL);
16667  assert(SCIPvarIsActive(var));
16668 
16669  return SCIPimplicsGetNBinImpls(var->implics, varfixing);
16670 }
16671 
16672 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
16673  * problem variable x, there are no implications for nonbinary variable x;
16674  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
16675  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
16676  * (see SCIPvarGetIndex())
16677  */
16679  SCIP_VAR* var, /**< active problem variable */
16680  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16681  )
16682 {
16683  assert(var != NULL);
16684  assert(SCIPvarIsActive(var));
16685 
16686  return SCIPimplicsGetVars(var->implics, varfixing);
16687 }
16688 
16689 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
16690  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
16691  * there are no implications for nonbinary variable x
16692  */
16694  SCIP_VAR* var, /**< active problem variable */
16695  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16696  )
16697 {
16698  assert(var != NULL);
16699  assert(SCIPvarIsActive(var));
16700 
16701  return SCIPimplicsGetTypes(var->implics, varfixing);
16702 }
16703 
16704 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
16705  * variable x, there are no implications for nonbinary variable x
16706  */
16708  SCIP_VAR* var, /**< active problem variable */
16709  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16710  )
16711 {
16712  assert(var != NULL);
16713  assert(SCIPvarIsActive(var));
16714 
16715  return SCIPimplicsGetBounds(var->implics, varfixing);
16716 }
16717 
16718 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
16719  * there are no implications for nonbinary variable x.
16720  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
16721  * its id is negative, otherwise it is nonnegative.
16722  */
16723 int* SCIPvarGetImplIds(
16724  SCIP_VAR* var, /**< active problem variable */
16725  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
16726  )
16727 {
16728  assert(var != NULL);
16729  assert(SCIPvarIsActive(var));
16730 
16731  return SCIPimplicsGetIds(var->implics, varfixing);
16732 }
16733 
16734 /** gets number of cliques, the active variable is contained in */
16735 int SCIPvarGetNCliques(
16736  SCIP_VAR* var, /**< active problem variable */
16737  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
16738  )
16739 {
16740  assert(var != NULL);
16741  assert(SCIPvarIsActive(var));
16742 
16743  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
16744 }
16745 
16746 /** gets array of cliques, the active variable is contained in */
16748  SCIP_VAR* var, /**< active problem variable */
16749  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
16750  )
16751 {
16752  assert(var != NULL);
16753  assert(SCIPvarIsActive(var));
16754 
16755  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
16756 }
16757 
16758 /** gets primal LP solution value of variable */
16760  SCIP_VAR* var /**< problem variable */
16761  )
16762 {
16763  assert(var != NULL);
16764 
16766  return SCIPcolGetPrimsol(var->data.col);
16767  else
16768  return SCIPvarGetLPSol_rec(var);
16769 }
16770 
16771 /** gets primal NLP solution value of variable */
16773  SCIP_VAR* var /**< problem variable */
16774  )
16775 {
16776  assert(var != NULL);
16777 
16779  return var->nlpsol;
16780  else
16781  return SCIPvarGetNLPSol_rec(var);
16782 }
16783 
16784 /** return lower bound change info at requested position */
16786  SCIP_VAR* var, /**< problem variable */
16787  int pos /**< requested position */
16788  )
16789 {
16790  assert(pos >= 0);
16791  assert(pos < var->nlbchginfos);
16792 
16793  return &var->lbchginfos[pos];
16794 }
16795 
16796 /** gets the number of lower bound change info array */
16798  SCIP_VAR* var /**< problem variable */
16799  )
16800 {
16801  return var->nlbchginfos;
16802 }
16803 
16804 /** return upper bound change info at requested position */
16806  SCIP_VAR* var, /**< problem variable */
16807  int pos /**< requested position */
16808  )
16809 {
16810  assert(pos >= 0);
16811  assert(pos < var->nubchginfos);
16812 
16813  return &var->ubchginfos[pos];
16814 }
16815 
16816 /** gets the number upper bound change info array */
16818  SCIP_VAR* var /**< problem variable */
16819  )
16820 {
16821  assert(var != NULL);
16822 
16823  return var->nubchginfos;
16824 }
16825 
16826 /** returns the value based history for the variable */
16828  SCIP_VAR* var /**< problem variable */
16829  )
16830 {
16831  assert(var != NULL);
16832 
16833  return var->valuehistory;
16834 }
16835 
16836 /** gets pseudo solution value of variable */
16838  SCIP_VAR* var /**< problem variable */
16839  )
16840 {
16841  assert(var != NULL);
16842 
16844  return SCIPvarGetBestBoundLocal(var);
16845  else
16846  return SCIPvarGetPseudoSol_rec(var);
16847 }
16848 
16849 /** returns the variable's VSIDS score */
16851  SCIP_VAR* var, /**< problem variable */
16852  SCIP_STAT* stat, /**< problem statistics */
16853  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16854  )
16855 {
16856  assert(var != NULL);
16857 
16859  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
16860  else
16861  return SCIPvarGetVSIDS_rec(var, stat, dir);
16862 }
16863 
16864 /** includes event handler with given data in variable's event filter */
16866  SCIP_VAR* var, /**< problem variable */
16867  BMS_BLKMEM* blkmem, /**< block memory */
16868  SCIP_SET* set, /**< global SCIP settings */
16869  SCIP_EVENTTYPE eventtype, /**< event type to catch */
16870  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
16871  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
16872  int* filterpos /**< pointer to store position of event filter entry, or NULL */
16873  )
16874 {
16875  assert(var != NULL);
16876  assert(set != NULL);
16877  assert(var->scip == set->scip);
16878  assert(var->eventfilter != NULL);
16879  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
16880  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
16881  assert(SCIPvarIsTransformed(var));
16882 
16883  SCIPdebugMessage("catch event of type 0x%x of variable <%s> with handler %p and data %p\n",
16884  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
16885 
16886  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
16887 
16888  return SCIP_OKAY;
16889 }
16890 
16891 /** deletes event handler with given data from variable's event filter */
16893  SCIP_VAR* var, /**< problem variable */
16894  BMS_BLKMEM* blkmem, /**< block memory */
16895  SCIP_SET* set, /**< global SCIP settings */
16896  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
16897  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
16898  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
16899  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
16900  )
16901 {
16902  assert(var != NULL);
16903  assert(set != NULL);
16904  assert(var->scip == set->scip);
16905  assert(var->eventfilter != NULL);
16906  assert(SCIPvarIsTransformed(var));
16907 
16908  SCIPdebugMessage("drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr, (void*)eventdata);
16909 
16910  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
16911 
16912  return SCIP_OKAY;
16913 }
16914 
16915 /** returns the position of the bound change index */
16916 int SCIPbdchgidxGetPos(
16917  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
16918  )
16919 {
16920  assert(bdchgidx != NULL);
16921 
16922  return bdchgidx->pos;
16923 }
16924 
16925 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
16927  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
16928  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
16929  )
16930 {
16931  assert(bdchgidx1 != NULL);
16932  assert(bdchgidx1->depth >= -2);
16933  assert(bdchgidx1->pos >= 0);
16934  assert(bdchgidx2 != NULL);
16935  assert(bdchgidx2->depth >= -2);
16936  assert(bdchgidx2->pos >= 0);
16937 
16938  return (bdchgidx1->depth < bdchgidx2->depth)
16939  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
16940 }
16941 
16942 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
16943  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
16944  * last bound change was applied to the current node
16945  */
16947  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
16948  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
16949  )
16950 {
16951  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
16952  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
16953  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
16954  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
16955 
16956  if( bdchgidx1 == NULL )
16957  return FALSE;
16958  else if( bdchgidx2 == NULL )
16959  return TRUE;
16960  else
16961  return (bdchgidx1->depth < bdchgidx2->depth)
16962  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
16963 }
16964 
16965 /** returns old bound that was overwritten for given bound change information */
16967  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
16968  )
16969 {
16970  assert(bdchginfo != NULL);
16971 
16972  return bdchginfo->oldbound;
16973 }
16974 
16975 /** returns new bound installed for given bound change information */
16977  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
16978  )
16979 {
16980  assert(bdchginfo != NULL);
16981 
16982  return bdchginfo->newbound;
16983 }
16984 
16985 /** returns variable that belongs to the given bound change information */
16987  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
16988  )
16989 {
16990  assert(bdchginfo != NULL);
16991 
16992  return bdchginfo->var;
16993 }
16994 
16995 /** returns whether the bound change information belongs to a branching decision or a deduction */
16997  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
16998  )
16999 {
17000  assert(bdchginfo != NULL);
17001 
17002  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17003 }
17004 
17005 /** returns whether the bound change information belongs to a lower or upper bound change */
17007  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17008  )
17009 {
17010  assert(bdchginfo != NULL);
17011 
17012  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17013 }
17014 
17015 /** returns depth level of given bound change information */
17017  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17018  )
17019 {
17020  assert(bdchginfo != NULL);
17021 
17022  return bdchginfo->bdchgidx.depth;
17023 }
17024 
17025 /** returns bound change position in its depth level of given bound change information */
17027  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17028  )
17029 {
17030  assert(bdchginfo != NULL);
17031 
17032  return bdchginfo->bdchgidx.pos;
17033 }
17034 
17035 /** returns bound change index of given bound change information */
17037  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17038  )
17039 {
17040  assert(bdchginfo != NULL);
17041 
17042  return &bdchginfo->bdchgidx;
17043 }
17044 
17045 /** returns inference variable of given bound change information */
17047  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17048  )
17049 {
17050  assert(bdchginfo != NULL);
17053 
17054  return bdchginfo->inferencedata.var;
17055 }
17056 
17057 /** returns inference constraint of given bound change information */
17059  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17060  )
17061 {
17062  assert(bdchginfo != NULL);
17064  assert(bdchginfo->inferencedata.reason.cons != NULL);
17065 
17066  return bdchginfo->inferencedata.reason.cons;
17067 }
17068 
17069 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
17071  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17072  )
17073 {
17074  assert(bdchginfo != NULL);
17076 
17077  return bdchginfo->inferencedata.reason.prop;
17078 }
17079 
17080 /** returns inference user information of given bound change information */
17082  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17083  )
17084 {
17085  assert(bdchginfo != NULL);
17088 
17089  return bdchginfo->inferencedata.info;
17090 }
17091 
17092 /** returns inference bound of inference variable of given bound change information */
17094  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17095  )
17096 {
17097  assert(bdchginfo != NULL);
17100 
17101  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
17102 }
17103 
17104 /** returns the relaxed bound change type */
17106  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
17107  )
17108 {
17109  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
17110 }
17111 
17112 
17113 /** returns whether the bound change information belongs to a redundant bound change */
17115  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17116  )
17117 {
17118  assert(bdchginfo != NULL);
17119  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
17120 
17121  return bdchginfo->redundant;
17122 }
17123 
17124 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
17126  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17127  )
17128 {
17129  assert(bdchginfo != NULL);
17130 
17133  && bdchginfo->inferencedata.reason.prop != NULL);
17134 }
17135 
17136 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
17137  * has a tighter new bound as the second bound change
17138  */
17140  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
17141  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
17142  )
17143 {
17144  assert(bdchginfo1 != NULL);
17145  assert(bdchginfo2 != NULL);
17146  assert(bdchginfo1->var == bdchginfo2->var);
17147  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
17148 
17149  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
17150  ? bdchginfo1->newbound > bdchginfo2->newbound
17151  : bdchginfo1->newbound < bdchginfo2->newbound);
17152 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:51
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:499
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:15989
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:15943
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_LP *lp, 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:8978
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:15705
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_Bool *cutoff)
Definition: var.c:1307
SCIP_HOLELIST * holelist
Definition: struct_var.h:161
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_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:9861
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1650
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17106
static SCIP_RETCODE varRemoveImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1534
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1512
SCIP_RETCODE SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1358
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14014
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:4669
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:424
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:16530
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13111
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:925
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:16760
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:8850
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11177
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:14141
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:85
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:512
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:2372
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16114
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:4715
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5087
internal methods for storing primal CIP solutions
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17017
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:431
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:13661
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8732
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:15775
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12466
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:16436
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:12995
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:19105
int nubchginfos
Definition: struct_var.h:260
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16977
internal methods for branch and bound tree
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:110
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:544
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5642
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14912
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:194
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4195
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:15735
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:15695
unsigned int inferboundtype
Definition: struct_var.h:91
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16183
char * name
Definition: struct_var.h:226
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:15808
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17059
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:963
unsigned int boundchgtype
Definition: struct_var.h:112
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_VAR *var)
Definition: prob.c:1126
union SCIP_BoundChg::@11 data
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition: implics.c:1224
SCIP_HOLE hole
Definition: struct_var.h:49
SCIP_Real bestrootsol
Definition: struct_var.h:204
char * name
Definition: struct_lp.h:211
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17071
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5007
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1758
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:127
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:84
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5466
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:2058
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13562
methods for implications, variable bounds, and cliques
SCIP_RETCODE SCIPeventqueueAdd(SCIP_EVENTQUEUE *eventqueue, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENT **event)
Definition: event.c:2057
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1443
#define SCIP_MAXSTRLEN
Definition: def.h:196
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:16574
SCIP_DOM origdom
Definition: struct_var.h:167
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:12771
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16009
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:724
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2323
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6055
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:15788
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:123
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:528
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:4762
SCIP_Real lastbranchvalue
Definition: struct_stat.h:106
#define NULL
Definition: lpi_spx.cpp:129
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1033
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:240
#define MAXABSVBCOEF
Definition: var.c:65
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:14966
SCIP_RETCODE SCIPeventfilterDel(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int filterpos)
Definition: event.c:1808
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14624
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:6950
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:15365
SCIP_Real constant
Definition: struct_var.h:182
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int addnlocksdown, int addnlocksup)
Definition: var.c:3044
SCIP_Real bestrootredcost
Definition: struct_var.h:205
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8034
SCIP_HISTORY * historycrun
Definition: struct_var.h:242
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:136
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:2404
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1369
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6114
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11544
SCIP_Longint closestvblpcount
Definition: struct_var.h:244
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:8342
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:2401
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:6250
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:2281
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:4531
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14442
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:152
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:16336
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16648
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:18470
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3444
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16736
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:240
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:18318
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5688
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:13747
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12120
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:123
unsigned int nboundchgs
Definition: struct_var.h:121
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17037
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:16866
SCIP_RETCODE SCIPcolCreate(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, int len, SCIP_ROW **rows, SCIP_Real *vals, SCIP_Bool removable)
Definition: lp.c:3086
SCIP_HOLELIST * newlist
Definition: struct_var.h:57
SCIP_Real right
Definition: struct_var.h:43
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:280
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5609
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:40
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:16542
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17047
#define FALSE
Definition: def.h:52
int lppos
Definition: struct_lp.h:159
#define EPSEQ(x, y, eps)
Definition: def.h:147
#define EPSISINT(x, eps)
Definition: def.h:159
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_Real newbound)
Definition: var.c:6496
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:19095
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5120
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:477
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:96
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1272
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:16636
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:16604
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17082
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:749
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3287
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14822
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:67
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:15875
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_Bool *cutoff)
Definition: var.c:834
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3023
SCIP_Real constant
Definition: struct_var.h:192
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:7579
SCIP_STAGE stage
Definition: struct_set.h:57
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:4751
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:15755
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:281
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:13633
#define TRUE
Definition: def.h:51
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5590
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:16947
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13970
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:109
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14779
SCIP_HOLELIST * oldlist
Definition: struct_var.h:58
#define MAXIMPLSCLOSURE
Definition: var.c:62
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:610
int nlbchginfos
Definition: struct_var.h:258
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:15362
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_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:4702
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2848
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1757
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:2015
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16147
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:170
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7717
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5624
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:4264
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:53
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_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:9510
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:7691
SCIP_Real SCIPvarGetRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12599
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2807
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9236
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:1881
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:939
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14667
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:16380
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:457
#define SCIPdebugMessage
Definition: pub_message.h:77
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:15853
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12651
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1478
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11241
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:1892
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12443
FILE * file
Definition: struct_vbc.h:39
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:16917
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:2413
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:16562
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10713
int index
Definition: struct_var.h:245
SCIP_Real constant
Definition: struct_var.h:175
unsigned int domchgtype
Definition: struct_var.h:140
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:4773
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1521
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:15417
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13359
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1761
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6005
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1174
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:239
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:16446
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16136
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11054
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:612
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12329
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12536
SCIP_HOLECHG * holechgs
Definition: struct_var.h:132
SCIP_Real obj
Definition: struct_var.h:201
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14354
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:5219
SCIP_Real relaxsol
Definition: struct_var.h:207
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:893
int conflictlbcount
Definition: struct_var.h:261
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:12984
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10532
internal methods for LP management
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16195
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:389
SCIP_VAR ** vars
Definition: struct_var.h:184
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:189
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11169
internal methods for branching and inference history
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:16927
int nrootintfixings
Definition: struct_stat.h:164
int branchpriority
Definition: struct_var.h:256
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_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:10215
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_LP *lp)
Definition: primal.c:360
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:15841
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:515
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1189
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:2265
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16708
SCIP * scip
Definition: struct_set.h:58
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:15490
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:199
SCIP_VAR * var
Definition: struct_var.h:176
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:95
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12190
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:16838
int nrootboundchgs
Definition: struct_stat.h:162
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:140
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:4739
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:7026
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:131
internal methods for propagators
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_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:4924
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:1966
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14534
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16062
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:16773
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:445
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:6727
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1480
SCIP_Real conflictrelaxedub
Definition: struct_var.h:213
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16042
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16205
unsigned int inferboundtype
Definition: struct_var.h:114
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:472
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16679
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:7440
union SCIP_Var::@12 data
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:4703
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12074
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:235
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, SCIP_VARTYPE vartype)
Definition: var.c:5723
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:18396
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:16552
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10734
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:1672
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:16584
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:16482
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:213
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:212
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10924
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13421
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:15979
SCIP_AGGREGATE aggregate
Definition: struct_var.h:222
SCIP_Real lazylb
Definition: struct_var.h:214
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:414
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16072
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:7064
SCIP_Bool history_valuebased
Definition: struct_set.h:217
SCIP_RETCODE SCIPeventfilterAdd(SCIP_EVENTFILTER *eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: event.c:1715
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:6973
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:7279
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:16240
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:470
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2332
internal methods for storing and manipulating the main problem
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15233
#define SCIPerrorMessage
Definition: pub_message.h:45
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16021
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:16034
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1085
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:234
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15325
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:984
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:15359
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:375
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:1026
SCIP_Longint lpcount
Definition: struct_stat.h:137
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:18361
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:728
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:5774
int lbchginfossize
Definition: struct_var.h:257
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11512
unsigned int varstatus
Definition: struct_var.h:271
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2762
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:625
SCIP_Real bestrootlpobjval
Definition: struct_var.h:206
SCIP_VARDATA * vardata
Definition: struct_var.h:231
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:5942
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:16818
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13470
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:15818
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:209
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:7680
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12049
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7557
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3363
SCIP_HOLECHG * holechgs
Definition: struct_var.h:142
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:16798
unsigned int pos
Definition: struct_var.h:111
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1849
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:146
SCIP_VAR * transvar
Definition: struct_var.h:168
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:153
#define MAXDNOM
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16125
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5157
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:94
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:411
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1759
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:486
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:584
unsigned int initial
Definition: struct_var.h:265
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14579
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13186
SCIP_NEGATE negate
Definition: struct_var.h:224
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11234
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4142
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:73
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:7117
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:12851
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:130
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:2289
#define REALABS(x)
Definition: def.h:146
int nparentvars
Definition: struct_var.h:252
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:13878
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
internal methods for global SCIP settings
#define SCIP_CALL(x)
Definition: def.h:258
SCIP_VBOUNDS * vubs
Definition: struct_var.h:235
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5071
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14309
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17007
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:14057
int SCIPimplicsGetNBinImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2314
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13517
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5417
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:2297
int closestvubidx
Definition: struct_var.h:264
internal methods for relaxators
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:405
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:15864
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:4691
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10868
SCIP_Real vsidsweight
Definition: struct_stat.h:95
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:7566
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:235
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10671
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16159
unsigned int eventmask
Definition: struct_event.h:179
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11139
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:13925
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16748
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2883
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15010
unsigned int branchdirection
Definition: struct_var.h:273
int ubchginfossize
Definition: struct_var.h:259
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1594
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5039
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:16456
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:236
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_Real newbound)
Definition: var.c:6668
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:96
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:326
int var_probindex
Definition: struct_lp.h:165
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3564
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:16508
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6039
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:417
internal methods for problem variables
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:12705
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:15798
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:5747
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10798
#define SCIP_UNKNOWN
Definition: def.h:143
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:4784
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_LP *lp, 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:9309
unsigned int vartype
Definition: struct_var.h:270
unsigned int SCIP_EVENTTYPE
Definition: type_event.h:125
unsigned int boundchgtype
Definition: struct_var.h:89
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:425
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:14225
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:6174
SCIP_VAR * var
Definition: struct_var.h:88
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:86
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3159
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:12805
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:8461
#define SCIP_Bool
Definition: def.h:49
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15066
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:16356
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2750
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:408
SCIP_Real ub
Definition: struct_var.h:160
unsigned int boundtype
Definition: struct_var.h:90
unsigned int deletable
Definition: struct_var.h:267
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:5796
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12455
SCIP_MULTAGGR multaggr
Definition: struct_var.h:223
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7807
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:16806
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:538
unsigned int deleted
Definition: struct_var.h:268
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2353
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3491
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:7650
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2305
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:552
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:2384
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17094
unsigned int removable
Definition: struct_var.h:266
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:16616
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2548
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8100
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16082
unsigned int redundant
Definition: struct_var.h:93
SCIP_Real oldbound
Definition: struct_var.h:106
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16104
int closestvlbidx
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_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:5841
int nuses
Definition: struct_var.h:253
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14724
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12257
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:15829
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_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:6999
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:15743
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:59
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:102
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:16390
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:130
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15122
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:18328
int probindex
Definition: struct_var.h:246
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:8213
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:2100
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12912
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:560
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15342
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11452
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5023
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1492
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3277
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:13797
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3536
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3182
SCIP * scip
Definition: struct_var.h:199
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:238
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12377
int nlocksup
Definition: struct_var.h:255
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2080
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17115
int conflictubcount
Definition: struct_var.h:262
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:2273
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2193
SCIP_DOM locdom
Definition: struct_var.h:217
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16694
#define SCIP_REAL_MAX
Definition: def.h:124
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5281
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:243
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2820
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:401
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11220
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:15999
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:107
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:16227
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:599
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:16216
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:13258
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3428
SCIP_Real newbound
Definition: struct_var.h:82
#define SCIP_REAL_MIN
Definition: def.h:125
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3469
SCIP_VAR ** parentvars
Definition: struct_var.h:232
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:380
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2576
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5146
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16093
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:151
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:15968
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16987
#define SCIP_DEFAULT_INFINITY
Definition: def.h:128
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1199
SCIP_HOLELIST * next
Definition: struct_var.h:50
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:5784
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:16518
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:573
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:406
unsigned int boundtype
Definition: struct_var.h:113
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11226
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:662
static const SCIP_Real scalars[]
Definition: lp.c:5431
int lpipos
Definition: struct_lp.h:160
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:7263
SCIP_Longint domchgcount
Definition: struct_stat.h:84
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:15715
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3394
SCIP_Real lazyub
Definition: struct_var.h:215
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1675
unsigned int redundant
Definition: struct_var.h:115
SCIP_RETCODE SCIPvarChgUbGlobal(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:6810
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:3739
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:15953
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_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:5072
SCIP_VAR * var
Definition: struct_var.h:108
public methods for message output
int SCIPvarGetNBinImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16662
int nrootboundchgsrun
Definition: struct_stat.h:163
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:2422
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_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:4384
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:602
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17126
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13051
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:8752
SCIP_Real * scalars
Definition: struct_var.h:183
SCIP_IMPLICS * implics
Definition: struct_var.h:236
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:4727
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12836
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10413
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:97
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:349
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8699
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:145
#define SCIP_Real
Definition: def.h:123
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:104
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2649
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:1223
#define MIN(x, y)
Definition: memory.c:59
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5098
int parentvarssize
Definition: struct_var.h:251
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:15685
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:237
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:16013
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16851
#define SCIP_INVALID
Definition: def.h:142
internal methods for constraints and constraint handlers
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:16469
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition: event.c:636
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_RETCODE SCIPvarParseTransformed(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, SCIP_STAT *stat, const char *str, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata, char **endptr, SCIP_Bool *success)
Definition: var.c:2465
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2222
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3214
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:494
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10433
SCIP_Real branchfactor
Definition: struct_var.h:202
unsigned int donotmultaggr
Definition: struct_var.h:269
#define SCIP_Longint
Definition: def.h:107
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5270
SCIP_Real nlpsol
Definition: struct_var.h:208
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:132
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2524
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14865
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:16426
SCIP_Real lb
Definition: struct_var.h:159
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:16594
SCIP_VAR * var
Definition: struct_lp.h:147
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5055
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:8590
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:15725
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7968
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:18338
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2789
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:16400
SCIP_DOM glbdom
Definition: struct_var.h:216
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:4553
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:586
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2007
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:58
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6212
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:16626
SCIP_Bool collectvarhistory
Definition: struct_stat.h:212
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15141
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11432
SCIP_VAR * negatedvar
Definition: struct_var.h:233
SCIP_Real newbound
Definition: struct_var.h:107
int nlocksdown
Definition: struct_var.h:254
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:2362
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8161
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:14996
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6022
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6282
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:404
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5292
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11962
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:16893
SCIP_Real rootsol
Definition: struct_var.h:203
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2379
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:1901
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:15889
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:15930
SCIP_HISTORY * history
Definition: struct_var.h:241
common defines and data types used in all packages of SCIP
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14485
int nrootintfixingsrun
Definition: struct_stat.h:165
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:371
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:15917
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11835
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:54
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16997
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:76
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:8881
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:15402
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_Real newbound)
Definition: var.c:6322
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:2341
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:15907
SCIP_ORIGINAL original
Definition: struct_var.h:220
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:16316
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3686
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:15891
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17027
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:16495
#define SCIP_ALLOC(x)
Definition: def.h:269
#define SCIPABORT()
Definition: def.h:230
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:16786
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14397
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16032
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:561
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:55
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11750
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7902
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:16370
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:6595
unsigned int applied
Definition: struct_var.h:92
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:66
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10615
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16052
SCIP_HOLELIST ** ptr
Definition: struct_var.h:56
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:16413
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:16724
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:390
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:141
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:15765
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5677
SCIP_COL * col
Definition: struct_var.h:221
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5501
SCIP_Real left
Definition: struct_var.h:42
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:6706
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:1345
#define EPSZ(x, eps)
Definition: def.h:152
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_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10446
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:872
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16171
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:518
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_vbc.h:40
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3269
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:10987
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:882
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11657
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:16967
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:16828
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5109
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:239
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:13606
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1557
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:5328
SCIP_Real scalar
Definition: struct_var.h:174
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:17140
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10653