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-2020 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not visit scipopt.org. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @ingroup OTHER_CFILES
18  * @brief methods for problem variables
19  * @author Tobias Achterberg
20  * @author Timo Berthold
21  * @author Gerald Gamrath
22  * @author Stefan Heinz
23  * @author Marc Pfetsch
24  * @author Michael Winkler
25  * @author Kati Wolter
26  * @author Stefan Vigerske
27  *
28  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
29  * corresponding linear constraint if it exists. This seems to require some work, since the linear
30  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
31  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
32  * changed. This has to be done with care in order to not loose the performance gains of
33  * multi-aggregation.
34  */
35 
36 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
37 
38 #include "scip/cons.h"
39 #include "scip/event.h"
40 #include "scip/history.h"
41 #include "scip/implics.h"
42 #include "scip/lp.h"
43 #include "scip/primal.h"
44 #include "scip/prob.h"
45 #include "scip/pub_cons.h"
46 #include "scip/pub_history.h"
47 #include "scip/pub_implics.h"
48 #include "scip/pub_lp.h"
49 #include "scip/pub_message.h"
50 #include "scip/pub_misc.h"
51 #include "scip/pub_misc_sort.h"
52 #include "scip/pub_prop.h"
53 #include "scip/pub_var.h"
54 #include "scip/relax.h"
55 #include "scip/set.h"
56 #include "scip/sol.h"
57 #include "scip/stat.h"
58 #include "scip/struct_event.h"
59 #include "scip/struct_lp.h"
60 #include "scip/struct_prob.h"
61 #include "scip/struct_set.h"
62 #include "scip/struct_stat.h"
63 #include "scip/struct_var.h"
64 #include "scip/tree.h"
65 #include "scip/var.h"
66 #include <string.h>
67 
68 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
69  * in implication graph */
70 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
71 
72 /*
73  * hole, holelist, and domain methods
74  */
75 
76 /** creates a new holelist element */
77 static
79  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
80  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
81  SCIP_SET* set, /**< global SCIP settings */
82  SCIP_Real left, /**< left bound of open interval in new hole */
83  SCIP_Real right /**< right bound of open interval in new hole */
84  )
85 {
86  assert(holelist != NULL);
87  assert(blkmem != NULL);
88  assert(SCIPsetIsLT(set, left, right));
89 
90  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
91 
92  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
93  (*holelist)->hole.left = left;
94  (*holelist)->hole.right = right;
95  (*holelist)->next = NULL;
96 
97  return SCIP_OKAY;
98 }
99 
100 /** frees all elements in the holelist */
101 static
102 void holelistFree(
103  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
104  BMS_BLKMEM* blkmem /**< block memory for target holelist */
105  )
106 {
107  assert(holelist != NULL);
108  assert(blkmem != NULL);
109 
110  while( *holelist != NULL )
111  {
112  SCIP_HOLELIST* next;
113 
114  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
115  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
116 
117  next = (*holelist)->next;
118  BMSfreeBlockMemory(blkmem, holelist);
119  assert(*holelist == NULL);
120 
121  *holelist = next;
122  }
123  assert(*holelist == NULL);
124 }
125 
126 /** duplicates a list of holes */
127 static
129  SCIP_HOLELIST** target, /**< pointer to target holelist */
130  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
131  SCIP_SET* set, /**< global SCIP settings */
132  SCIP_HOLELIST* source /**< holelist to duplicate */
133  )
134 {
135  assert(target != NULL);
136 
137  while( source != NULL )
138  {
139  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
140  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
141  source = source->next;
142  target = &(*target)->next;
143  }
144 
145  return SCIP_OKAY;
146 }
147 
148 /** adds a hole to the domain */
149 static
151  SCIP_DOM* dom, /**< domain to add hole to */
152  BMS_BLKMEM* blkmem, /**< block memory */
153  SCIP_SET* set, /**< global SCIP settings */
154  SCIP_Real left, /**< left bound of open interval in new hole */
155  SCIP_Real right, /**< right bound of open interval in new hole */
156  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
157  )
158 {
159  SCIP_HOLELIST** insertpos;
160  SCIP_HOLELIST* next;
161 
162  assert(dom != NULL);
163  assert(added != NULL);
164 
165  /* search for the position of the new hole */
166  insertpos = &dom->holelist;
167  while( *insertpos != NULL && (*insertpos)->hole.left < left )
168  insertpos = &(*insertpos)->next;
169 
170  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
171  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
172  {
173  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
174  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
175  *added = FALSE;
176  return SCIP_OKAY;
177  }
178 
179  /* add hole */
180  *added = TRUE;
181 
182  next = *insertpos;
183  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
184  (*insertpos)->next = next;
185 
186  return SCIP_OKAY;
187 }
188 
189 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
190 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
191  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
192  * merge */
193 static
194 void domMerge(
195  SCIP_DOM* dom, /**< domain to merge */
196  BMS_BLKMEM* blkmem, /**< block memory */
197  SCIP_SET* set, /**< global SCIP settings */
198  SCIP_Real* newlb, /**< pointer to store new lower bound */
199  SCIP_Real* newub /**< pointer to store new upper bound */
200  )
201 {
202  SCIP_HOLELIST** holelistptr;
203  SCIP_HOLELIST** lastnextptr;
204  SCIP_Real* lastrightptr;
205 
206  assert(dom != NULL);
207  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
208 
209 #ifndef NDEBUG
210  {
211  /* check if the holelist is sorted w.r.t. to the left interval bounds */
212  SCIP_Real lastleft;
213 
214  holelistptr = &dom->holelist;
215 
216  lastleft = -SCIPsetInfinity(set);
217 
218  while( *holelistptr != NULL )
219  {
220  if( (*holelistptr)->next != NULL )
221  {
222  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
223  lastleft = (*holelistptr)->hole.left;
224  }
225 
226  holelistptr = &(*holelistptr)->next;
227  }
228  }
229 #endif
230 
231  SCIPsetDebugMsg(set, "merge hole list\n");
232 
233  holelistptr = &dom->holelist;
234  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
235  lastnextptr = holelistptr;
236 
237  while( *holelistptr != NULL )
238  {
239  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
240 
241  /* check that the hole is not empty */
242  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
243 
244  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
245  {
246  /* the remaining holes start behind the upper bound: remove them */
247  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
248  holelistFree(holelistptr, blkmem);
249  assert(*holelistptr == NULL);
250 
251  /* unlink this hole from the previous hole */
252  *lastnextptr = NULL;
253  }
254  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
255  {
256  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
257  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
258 
259  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
260 
261  /* adjust upper bound */
262  dom->ub = (*holelistptr)->hole.left;
263 
264  if(newub != NULL )
265  *newub = (*holelistptr)->hole.left;
266 
267  /* remove remaining hole list */
268  holelistFree(holelistptr, blkmem);
269  assert(*holelistptr == NULL);
270 
271  /* unlink this hole from the previous hole */
272  *lastnextptr = NULL;
273  }
274  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
275  {
276  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
277  * the last hole, delete this hole */
278  SCIP_HOLELIST* nextholelist;
279 
280  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
281  {
282  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
283  * the lower bound */
284  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
285  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
286 
287  /* adjust lower bound */
288  dom->lb = *lastrightptr;
289 
290  if(newlb != NULL )
291  *newlb = *lastrightptr;
292  }
293  else
294  {
295  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
296  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
297  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
298  }
299  nextholelist = (*holelistptr)->next;
300  (*holelistptr)->next = NULL;
301  holelistFree(holelistptr, blkmem);
302 
303  /* connect the linked list after removing the hole */
304  *lastnextptr = nextholelist;
305 
306  /* get next hole */
307  *holelistptr = nextholelist;
308  }
309  else
310  {
311  /* the holes do not overlap: update lastholelist and lastrightptr */
312  lastrightptr = &(*holelistptr)->hole.right;
313  lastnextptr = &(*holelistptr)->next;
314 
315  /* get next hole */
316  holelistptr = &(*holelistptr)->next;
317  }
318  }
319 
320 #ifndef NDEBUG
321  {
322  /* check that holes are merged */
323  SCIP_Real lastright;
324 
325  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
326  holelistptr = &dom->holelist;
327 
328  while( *holelistptr != NULL )
329  {
330  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
331  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
332 
333  /* check the hole property (check that the hole is not empty) */
334  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
335  lastright = (*holelistptr)->hole.right;
336 
337  /* get next hole */
338  holelistptr = &(*holelistptr)->next;
339  }
340 
341  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
342  assert( SCIPsetIsLE(set, lastright, dom->ub) );
343  }
344 #endif
345 }
346 
347 /*
348  * domain change methods
349  */
350 
351 /** ensures, that bound change info array for lower bound changes can store at least num entries */
352 static
354  SCIP_VAR* var, /**< problem variable */
355  BMS_BLKMEM* blkmem, /**< block memory */
356  SCIP_SET* set, /**< global SCIP settings */
357  int num /**< minimum number of entries to store */
358  )
359 {
360  assert(var != NULL);
361  assert(var->nlbchginfos <= var->lbchginfossize);
362  assert(SCIPvarIsTransformed(var));
363 
364  if( num > var->lbchginfossize )
365  {
366  int newsize;
367 
368  newsize = SCIPsetCalcMemGrowSize(set, num);
369  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
370  var->lbchginfossize = newsize;
371  }
372  assert(num <= var->lbchginfossize);
373 
374  return SCIP_OKAY;
375 }
376 
377 /** ensures, that bound change info array for upper bound changes can store at least num entries */
378 static
380  SCIP_VAR* var, /**< problem variable */
381  BMS_BLKMEM* blkmem, /**< block memory */
382  SCIP_SET* set, /**< global SCIP settings */
383  int num /**< minimum number of entries to store */
384  )
385 {
386  assert(var != NULL);
387  assert(var->nubchginfos <= var->ubchginfossize);
388  assert(SCIPvarIsTransformed(var));
389 
390  if( num > var->ubchginfossize )
391  {
392  int newsize;
393 
394  newsize = SCIPsetCalcMemGrowSize(set, num);
395  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
396  var->ubchginfossize = newsize;
397  }
398  assert(num <= var->ubchginfossize);
399 
400  return SCIP_OKAY;
401 }
402 
403 /** adds domain change info to the variable's lower bound change info array */
404 static
406  SCIP_VAR* var, /**< problem variable */
407  BMS_BLKMEM* blkmem, /**< block memory */
408  SCIP_SET* set, /**< global SCIP settings */
409  SCIP_Real oldbound, /**< old value for bound */
410  SCIP_Real newbound, /**< new value for bound */
411  int depth, /**< depth in the tree, where the bound change takes place */
412  int pos, /**< position of the bound change in its bound change array */
413  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
414  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
415  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
416  int inferinfo, /**< user information for inference to help resolving the conflict */
417  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
418  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
419  )
420 {
421  assert(var != NULL);
422  assert(SCIPsetIsLT(set, oldbound, newbound));
423  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
424  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
425  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
426  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
427  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
428  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
429  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
430 
431  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
432  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
433  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
434  oldbound, newbound);
435 
436  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
437  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
438  var->lbchginfos[var->nlbchginfos].newbound = newbound;
439  var->lbchginfos[var->nlbchginfos].var = var;
440  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
441  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
442  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
443  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
444  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
445  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
446  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
447  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
448  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
449 
450  /**@note The "pos" data member of the bound change info has a size of 27 bits */
451  assert(var->nlbchginfos < 1 << 27);
452 
453  switch( boundchgtype )
454  {
456  break;
458  assert(infercons != NULL);
459  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
460  break;
462  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
463  break;
464  default:
465  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
466  return SCIP_INVALIDDATA;
467  }
468 
469  var->nlbchginfos++;
470 
471  assert(var->nlbchginfos < 2
473  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
474 
475  return SCIP_OKAY;
476 }
477 
478 /** adds domain change info to the variable's upper bound change info array */
479 static
481  SCIP_VAR* var, /**< problem variable */
482  BMS_BLKMEM* blkmem, /**< block memory */
483  SCIP_SET* set, /**< global SCIP settings */
484  SCIP_Real oldbound, /**< old value for bound */
485  SCIP_Real newbound, /**< new value for bound */
486  int depth, /**< depth in the tree, where the bound change takes place */
487  int pos, /**< position of the bound change in its bound change array */
488  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
489  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
490  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
491  int inferinfo, /**< user information for inference to help resolving the conflict */
492  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
493  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
494  )
495 {
496  assert(var != NULL);
497  assert(SCIPsetIsGT(set, oldbound, newbound));
498  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
499  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
500  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
501  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
502  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
503  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
504  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
505 
506  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
507  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
508  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
509  oldbound, newbound);
510 
511  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
512  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
513  var->ubchginfos[var->nubchginfos].newbound = newbound;
514  var->ubchginfos[var->nubchginfos].var = var;
515  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
516  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
517  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
518  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
519  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
520  var->ubchginfos[var->nubchginfos].redundant = FALSE;
521  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
522  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
523  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
524 
525  /**@note The "pos" data member of the bound change info has a size of 27 bits */
526  assert(var->nubchginfos < 1 << 27);
527 
528  switch( boundchgtype )
529  {
531  break;
533  assert(infercons != NULL);
534  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
535  break;
537  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
538  break;
539  default:
540  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
541  return SCIP_INVALIDDATA;
542  }
543 
544  var->nubchginfos++;
545 
546  assert(var->nubchginfos < 2
548  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
549 
550  return SCIP_OKAY;
551 }
552 
553 /** applies single bound change */
555  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
556  BMS_BLKMEM* blkmem, /**< block memory */
557  SCIP_SET* set, /**< global SCIP settings */
558  SCIP_STAT* stat, /**< problem statistics */
559  SCIP_LP* lp, /**< current LP data */
560  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
561  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
562  int depth, /**< depth in the tree, where the bound change takes place */
563  int pos, /**< position of the bound change in its bound change array */
564  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
565  )
566 {
567  SCIP_VAR* var;
568 
569  assert(boundchg != NULL);
570  assert(stat != NULL);
571  assert(depth > 0);
572  assert(pos >= 0);
573  assert(cutoff != NULL);
574 
575  *cutoff = FALSE;
576 
577  /* ignore redundant bound changes */
578  if( boundchg->redundant )
579  return SCIP_OKAY;
580 
581  var = boundchg->var;
582  assert(var != NULL);
584  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
585 
586  /* apply bound change */
587  switch( boundchg->boundtype )
588  {
590  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
591  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
592  {
593  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
594  {
595  /* add the bound change info to the variable's bound change info array */
596  switch( boundchg->boundchgtype )
597  {
599  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
600  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
601  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
603  stat->lastbranchvar = var;
605  stat->lastbranchvalue = boundchg->newbound;
606  break;
607 
609  assert(boundchg->data.inferencedata.reason.cons != NULL);
610  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
611  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
612  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
613  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
614  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
615  boundchg->data.inferencedata.info,
617  break;
618 
620  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
621  boundchg->data.inferencedata.reason.prop != NULL
622  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
623  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
624  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
625  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
626  boundchg->data.inferencedata.info,
628  break;
629 
630  default:
631  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
632  return SCIP_INVALIDDATA;
633  }
634 
635  /* change local bound of variable */
636  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
637  }
638  else
639  {
640  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
641  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
642  *cutoff = TRUE;
643  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
644  }
645  }
646  else
647  {
648  /* mark bound change to be inactive */
649  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
650  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
651  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
652  boundchg->redundant = TRUE;
653  }
654  break;
655 
657  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
658  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
659  {
660  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
661  {
662  /* add the bound change info to the variable's bound change info array */
663  switch( boundchg->boundchgtype )
664  {
666  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
667  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
668  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
670  stat->lastbranchvar = var;
672  stat->lastbranchvalue = boundchg->newbound;
673  break;
674 
676  assert(boundchg->data.inferencedata.reason.cons != NULL);
677  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
678  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
679  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
680  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
681  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
682  boundchg->data.inferencedata.info,
684  break;
685 
687  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
688  boundchg->data.inferencedata.reason.prop != NULL
689  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
690  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
691  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
692  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
693  boundchg->data.inferencedata.info,
695  break;
696 
697  default:
698  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
699  return SCIP_INVALIDDATA;
700  }
701 
702  /* change local bound of variable */
703  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
704  }
705  else
706  {
707  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
708  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
709  *cutoff = TRUE;
710  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
711  }
712  }
713  else
714  {
715  /* mark bound change to be inactive */
716  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
717  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
718  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
719  boundchg->redundant = TRUE;
720  }
721  break;
722 
723  default:
724  SCIPerrorMessage("unknown bound type\n");
725  return SCIP_INVALIDDATA;
726  }
727 
728  /* update the branching and inference history */
729  if( !boundchg->applied && !boundchg->redundant )
730  {
731  assert(var == boundchg->var);
732 
734  {
735  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
738  }
739  else if( stat->lastbranchvar != NULL )
740  {
741  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
742  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
743  }
744  boundchg->applied = TRUE;
745  }
746 
747  return SCIP_OKAY;
748 }
749 
750 /** undoes single bound change */
752  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
753  BMS_BLKMEM* blkmem, /**< block memory */
754  SCIP_SET* set, /**< global SCIP settings */
755  SCIP_STAT* stat, /**< problem statistics */
756  SCIP_LP* lp, /**< current LP data */
757  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
758  SCIP_EVENTQUEUE* eventqueue /**< event queue */
759  )
760 {
761  SCIP_VAR* var;
762 
763  assert(boundchg != NULL);
764  assert(stat != NULL);
765 
766  /* ignore redundant bound changes */
767  if( boundchg->redundant )
768  return SCIP_OKAY;
769 
770  var = boundchg->var;
771  assert(var != NULL);
773 
774  /* undo bound change: apply the previous bound change of variable */
775  switch( boundchg->boundtype )
776  {
778  var->nlbchginfos--;
779  assert(var->nlbchginfos >= 0);
780  assert(var->lbchginfos != NULL);
781  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
782  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
783 
784  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
785  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
788 
789  /* reinstall the previous local bound */
790  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
791  var->lbchginfos[var->nlbchginfos].oldbound) );
792 
793  /* in case all bound changes are removed the local bound should match the global bound */
794  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
795 
796  break;
797 
799  var->nubchginfos--;
800  assert(var->nubchginfos >= 0);
801  assert(var->ubchginfos != NULL);
802  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
803  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
804 
805  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
806  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
809 
810  /* reinstall the previous local bound */
811  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
812  var->ubchginfos[var->nubchginfos].oldbound) );
813 
814  /* in case all bound changes are removed the local bound should match the global bound */
815  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
816 
817  break;
818 
819  default:
820  SCIPerrorMessage("unknown bound type\n");
821  return SCIP_INVALIDDATA;
822  }
823 
824  /* update last branching variable */
826  {
827  stat->lastbranchvar = NULL;
829  }
830 
831  return SCIP_OKAY;
832 }
833 
834 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
835 static
837  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
838  BMS_BLKMEM* blkmem, /**< block memory */
839  SCIP_SET* set, /**< global SCIP settings */
840  SCIP_STAT* stat, /**< problem statistics */
841  SCIP_LP* lp, /**< current LP data */
842  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
843  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
844  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
845  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
846  )
847 {
848  SCIP_VAR* var;
849  SCIP_Real newbound;
850  SCIP_BOUNDTYPE boundtype;
851 
852  assert(boundchg != NULL);
853  assert(cutoff != NULL);
854 
855  *cutoff = FALSE;
856 
857  /* ignore redundant bound changes */
858  if( boundchg->redundant )
859  return SCIP_OKAY;
860 
861  var = SCIPboundchgGetVar(boundchg);
862  newbound = SCIPboundchgGetNewbound(boundchg);
863  boundtype = SCIPboundchgGetBoundtype(boundchg);
864 
865  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
866  * after that bound change was applied
867  *
868  * @note a global bound change is not captured by the redundant member of the bound change data structure
869  */
870  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
871  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
872  {
873  return SCIP_OKAY;
874  }
875 
876  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
878  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
879 
880  /* check for cutoff */
881  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
882  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
883  {
884  *cutoff = TRUE;
885  return SCIP_OKAY;
886  }
887 
888  /* apply bound change */
889  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
890 
891  return SCIP_OKAY;
892 }
893 
894 /** captures branching and inference data of bound change */
895 static
897  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
898  )
899 {
900  assert(boundchg != NULL);
901 
902  /* capture variable associated with the bound change */
903  assert(boundchg->var != NULL);
904  SCIPvarCapture(boundchg->var);
905 
906  switch( boundchg->boundchgtype )
907  {
910  break;
911 
913  assert(boundchg->data.inferencedata.var != NULL);
914  assert(boundchg->data.inferencedata.reason.cons != NULL);
915  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
916  break;
917 
918  default:
919  SCIPerrorMessage("invalid bound change type\n");
920  return SCIP_INVALIDDATA;
921  }
922 
923  return SCIP_OKAY;
924 }
925 
926 /** releases branching and inference data of bound change */
927 static
929  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
930  BMS_BLKMEM* blkmem, /**< block memory */
931  SCIP_SET* set, /**< global SCIP settings */
932  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
933  SCIP_LP* lp /**< current LP data */
934 
935  )
936 {
937  assert(boundchg != NULL);
938 
939  switch( boundchg->boundchgtype )
940  {
943  break;
944 
946  assert(boundchg->data.inferencedata.var != NULL);
947  assert(boundchg->data.inferencedata.reason.cons != NULL);
948  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
949  break;
950 
951  default:
952  SCIPerrorMessage("invalid bound change type\n");
953  return SCIP_INVALIDDATA;
954  }
955 
956  /* release variable */
957  assert(boundchg->var != NULL);
958  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
959 
960  return SCIP_OKAY;
961 }
962 
963 /** creates empty domain change data with dynamic arrays */
964 static
966  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
967  BMS_BLKMEM* blkmem /**< block memory */
968  )
969 {
970  assert(domchg != NULL);
971  assert(blkmem != NULL);
972 
973  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
974  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
975  (*domchg)->domchgdyn.nboundchgs = 0;
976  (*domchg)->domchgdyn.boundchgs = NULL;
977  (*domchg)->domchgdyn.nholechgs = 0;
978  (*domchg)->domchgdyn.holechgs = NULL;
979  (*domchg)->domchgdyn.boundchgssize = 0;
980  (*domchg)->domchgdyn.holechgssize = 0;
981 
982  return SCIP_OKAY;
983 }
984 
985 /** frees domain change data */
987  SCIP_DOMCHG** domchg, /**< pointer to domain change */
988  BMS_BLKMEM* blkmem, /**< block memory */
989  SCIP_SET* set, /**< global SCIP settings */
990  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
991  SCIP_LP* lp /**< current LP data */
992  )
993 {
994  assert(domchg != NULL);
995  assert(blkmem != NULL);
996 
997  if( *domchg != NULL )
998  {
999  int i;
1000 
1001  /* release variables, branching and inference data associated with the bound changes */
1002  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1003  {
1004  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1005  }
1006 
1007  /* free memory for bound and hole changes */
1008  switch( (*domchg)->domchgdyn.domchgtype )
1009  {
1010  case SCIP_DOMCHGTYPE_BOUND:
1011  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1012  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1013  break;
1014  case SCIP_DOMCHGTYPE_BOTH:
1015  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1016  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1017  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1018  break;
1020  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1021  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1022  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1023  break;
1024  default:
1025  SCIPerrorMessage("invalid domain change type\n");
1026  return SCIP_INVALIDDATA;
1027  }
1028  }
1029 
1030  return SCIP_OKAY;
1031 }
1032 
1033 /** converts a static domain change data into a dynamic one */
1034 static
1036  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1037  BMS_BLKMEM* blkmem /**< block memory */
1038  )
1039 {
1040  assert(domchg != NULL);
1041  assert(blkmem != NULL);
1042 
1043  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1044 
1045  if( *domchg == NULL )
1046  {
1047  SCIP_CALL( domchgCreate(domchg, blkmem) );
1048  }
1049  else
1050  {
1051  switch( (*domchg)->domchgdyn.domchgtype )
1052  {
1053  case SCIP_DOMCHGTYPE_BOUND:
1054  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1055  (*domchg)->domchgdyn.nholechgs = 0;
1056  (*domchg)->domchgdyn.holechgs = NULL;
1057  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1058  (*domchg)->domchgdyn.holechgssize = 0;
1059  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1060  break;
1061  case SCIP_DOMCHGTYPE_BOTH:
1062  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1063  (*domchg)->domchgdyn.boundchgssize = (int) (*domchg)->domchgdyn.nboundchgs;
1064  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1065  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1066  break;
1068  break;
1069  default:
1070  SCIPerrorMessage("invalid domain change type\n");
1071  return SCIP_INVALIDDATA;
1072  }
1073  }
1074 #ifndef NDEBUG
1075  {
1076  int i;
1077  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1078  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1079  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1080  }
1081 #endif
1082 
1083  return SCIP_OKAY;
1084 }
1085 
1086 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1088  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1089  BMS_BLKMEM* blkmem, /**< block memory */
1090  SCIP_SET* set, /**< global SCIP settings */
1091  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1092  SCIP_LP* lp /**< current LP data */
1093  )
1094 {
1095  assert(domchg != NULL);
1096  assert(blkmem != NULL);
1097 
1098  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1099 
1100  if( *domchg != NULL )
1101  {
1102  switch( (*domchg)->domchgdyn.domchgtype )
1103  {
1104  case SCIP_DOMCHGTYPE_BOUND:
1105  if( (*domchg)->domchgbound.nboundchgs == 0 )
1106  {
1107  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1108  }
1109  break;
1110  case SCIP_DOMCHGTYPE_BOTH:
1111  if( (*domchg)->domchgboth.nholechgs == 0 )
1112  {
1113  if( (*domchg)->domchgbound.nboundchgs == 0 )
1114  {
1115  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1116  }
1117  else
1118  {
1119  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1120  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1121  }
1122  }
1123  break;
1125  if( (*domchg)->domchgboth.nholechgs == 0 )
1126  {
1127  if( (*domchg)->domchgbound.nboundchgs == 0 )
1128  {
1129  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1130  }
1131  else
1132  {
1133  /* shrink dynamic size arrays to their minimal sizes */
1134  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1135  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1136  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1137 
1138  /* convert into static domain change */
1139  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1140  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1141  }
1142  }
1143  else
1144  {
1145  /* shrink dynamic size arrays to their minimal sizes */
1146  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs, \
1147  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1148  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs, \
1149  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1150 
1151  /* convert into static domain change */
1152  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1153  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1154  }
1155  break;
1156  default:
1157  SCIPerrorMessage("invalid domain change type\n");
1158  return SCIP_INVALIDDATA;
1159  }
1160 #ifndef NDEBUG
1161  if( *domchg != NULL )
1162  {
1163  int i;
1164  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1165  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1166  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1167  }
1168 #endif
1169  }
1170 
1171  return SCIP_OKAY;
1172 }
1173 
1174 /** ensures, that boundchgs array can store at least num entries */
1175 static
1177  SCIP_DOMCHG* domchg, /**< domain change data structure */
1178  BMS_BLKMEM* blkmem, /**< block memory */
1179  SCIP_SET* set, /**< global SCIP settings */
1180  int num /**< minimum number of entries to store */
1181  )
1182 {
1183  assert(domchg != NULL);
1184  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1185 
1186  if( num > domchg->domchgdyn.boundchgssize )
1187  {
1188  int newsize;
1189 
1190  newsize = SCIPsetCalcMemGrowSize(set, num);
1191  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1192  domchg->domchgdyn.boundchgssize = newsize;
1193  }
1194  assert(num <= domchg->domchgdyn.boundchgssize);
1195 
1196  return SCIP_OKAY;
1197 }
1198 
1199 /** ensures, that holechgs array can store at least num additional entries */
1200 static
1202  SCIP_DOMCHG* domchg, /**< domain change data structure */
1203  BMS_BLKMEM* blkmem, /**< block memory */
1204  SCIP_SET* set, /**< global SCIP settings */
1205  int num /**< minimum number of additional entries to store */
1206  )
1207 {
1208  assert(domchg != NULL);
1209  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1210 
1211  if( num > domchg->domchgdyn.holechgssize )
1212  {
1213  int newsize;
1214 
1215  newsize = SCIPsetCalcMemGrowSize(set, num);
1216  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1217  domchg->domchgdyn.holechgssize = newsize;
1218  }
1219  assert(num <= domchg->domchgdyn.holechgssize);
1220 
1221  return SCIP_OKAY;
1222 }
1223 
1224 /** applies domain change */
1226  SCIP_DOMCHG* domchg, /**< domain change to apply */
1227  BMS_BLKMEM* blkmem, /**< block memory */
1228  SCIP_SET* set, /**< global SCIP settings */
1229  SCIP_STAT* stat, /**< problem statistics */
1230  SCIP_LP* lp, /**< current LP data */
1231  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1232  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1233  int depth, /**< depth in the tree, where the domain change takes place */
1234  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1235  )
1236 {
1237  int i;
1238 
1239  assert(cutoff != NULL);
1240 
1241  *cutoff = FALSE;
1242 
1243  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1244 
1245  if( domchg == NULL )
1246  return SCIP_OKAY;
1247 
1248  /* apply bound changes */
1249  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1250  {
1251  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1252  branchcand, eventqueue, depth, i, cutoff) );
1253  if( *cutoff )
1254  break;
1255  }
1256  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1257 
1258  /* mark all bound changes after a cutoff redundant */
1259  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1260  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1261 
1262  /* apply holelist changes */
1263  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1264  {
1265  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1266  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1267  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1268  }
1269 
1270  return SCIP_OKAY;
1271 }
1272 
1273 /** undoes domain change */
1275  SCIP_DOMCHG* domchg, /**< domain change to remove */
1276  BMS_BLKMEM* blkmem, /**< block memory */
1277  SCIP_SET* set, /**< global SCIP settings */
1278  SCIP_STAT* stat, /**< problem statistics */
1279  SCIP_LP* lp, /**< current LP data */
1280  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1281  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1282  )
1283 {
1284  int i;
1285 
1286  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1287  if( domchg == NULL )
1288  return SCIP_OKAY;
1289 
1290  /* undo holelist changes */
1291  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1292  {
1293  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1294  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1295  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1296  }
1297 
1298  /* undo bound changes */
1299  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1300  {
1301  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1302  }
1303  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1304 
1305  return SCIP_OKAY;
1306 }
1307 
1308 /** applies domain change to the global problem */
1310  SCIP_DOMCHG* domchg, /**< domain change to apply */
1311  BMS_BLKMEM* blkmem, /**< block memory */
1312  SCIP_SET* set, /**< global SCIP settings */
1313  SCIP_STAT* stat, /**< problem statistics */
1314  SCIP_LP* lp, /**< current LP data */
1315  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1316  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1317  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1318  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1319  )
1320 {
1321  int i;
1322 
1323  assert(cutoff != NULL);
1324 
1325  *cutoff = FALSE;
1326 
1327  if( domchg == NULL )
1328  return SCIP_OKAY;
1329 
1330  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1331 
1332  /* apply bound changes */
1333  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1334  {
1335  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1336  branchcand, eventqueue, cliquetable, cutoff) );
1337  if( *cutoff )
1338  break;
1339  }
1340  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1341 
1342  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1343 
1344  return SCIP_OKAY;
1345 }
1346 
1347 /** adds bound change to domain changes */
1349  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1350  BMS_BLKMEM* blkmem, /**< block memory */
1351  SCIP_SET* set, /**< global SCIP settings */
1352  SCIP_VAR* var, /**< variable to change the bounds for */
1353  SCIP_Real newbound, /**< new value for bound */
1354  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1355  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1356  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1357  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1358  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1359  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1360  int inferinfo, /**< user information for inference to help resolving the conflict */
1361  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1362  )
1363 {
1364  SCIP_BOUNDCHG* boundchg;
1365 
1366  assert(domchg != NULL);
1367  assert(var != NULL);
1369  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1370  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1371  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1372  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1373  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1374 
1375  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1376  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1377  newbound, var->name, (void*)domchg, (void*)*domchg);
1378 
1379  /* if domain change data doesn't exist, create it;
1380  * if domain change is static, convert it into dynamic change
1381  */
1382  if( *domchg == NULL )
1383  {
1384  SCIP_CALL( domchgCreate(domchg, blkmem) );
1385  }
1386  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1387  {
1388  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1389  }
1390  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1391 
1392  /* get memory for additional bound change */
1393  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1394 
1395  /* fill in the bound change data */
1396  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1397  boundchg->var = var;
1398  switch( boundchgtype )
1399  {
1401  boundchg->data.branchingdata.lpsolval = lpsolval;
1402  break;
1404  assert(infercons != NULL);
1405  boundchg->data.inferencedata.var = infervar;
1406  boundchg->data.inferencedata.reason.cons = infercons;
1407  boundchg->data.inferencedata.info = inferinfo;
1408  break;
1410  boundchg->data.inferencedata.var = infervar;
1411  boundchg->data.inferencedata.reason.prop = inferprop;
1412  boundchg->data.inferencedata.info = inferinfo;
1413  break;
1414  default:
1415  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1416  return SCIP_INVALIDDATA;
1417  }
1418 
1419  boundchg->newbound = newbound;
1420  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1421  boundchg->boundtype = boundtype; /*lint !e641*/
1422  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1423  boundchg->applied = FALSE;
1424  boundchg->redundant = FALSE;
1425  (*domchg)->domchgdyn.nboundchgs++;
1426 
1427  /* capture branching and inference data associated with the bound changes */
1428  SCIP_CALL( boundchgCaptureData(boundchg) );
1429 
1430 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1431 #ifdef SCIP_MORE_DEBUG
1432  {
1433  int i;
1434  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1435  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1436  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1437  }
1438 #endif
1439 #endif
1440 
1441  return SCIP_OKAY;
1442 }
1443 
1444 /** adds hole change to domain changes */
1446  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1447  BMS_BLKMEM* blkmem, /**< block memory */
1448  SCIP_SET* set, /**< global SCIP settings */
1449  SCIP_HOLELIST** ptr, /**< changed list pointer */
1450  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1451  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1452  )
1453 {
1454  SCIP_HOLECHG* holechg;
1455 
1456  assert(domchg != NULL);
1457  assert(ptr != NULL);
1458 
1459  /* if domain change data doesn't exist, create it;
1460  * if domain change is static, convert it into dynamic change
1461  */
1462  if( *domchg == NULL )
1463  {
1464  SCIP_CALL( domchgCreate(domchg, blkmem) );
1465  }
1466  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1467  {
1468  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1469  }
1470  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1471 
1472  /* get memory for additional hole change */
1473  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1474 
1475  /* fill in the hole change data */
1476  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1477  holechg->ptr = ptr;
1478  holechg->newlist = newlist;
1479  holechg->oldlist = oldlist;
1480  (*domchg)->domchgdyn.nholechgs++;
1481 
1482  return SCIP_OKAY;
1483 }
1484 
1485 
1486 
1487 
1488 /*
1489  * methods for variables
1490  */
1491 
1492 /** returns adjusted lower bound value, which is rounded for integral variable types */
1493 static
1495  SCIP_SET* set, /**< global SCIP settings */
1496  SCIP_VARTYPE vartype, /**< type of variable */
1497  SCIP_Real lb /**< lower bound to adjust */
1498  )
1499 {
1500  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1501  return -SCIPsetInfinity(set);
1502  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1503  return SCIPsetInfinity(set);
1504  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1505  return SCIPsetFeasCeil(set, lb);
1506  else if( SCIPsetIsZero(set, lb) )
1507  return 0.0;
1508  else
1509  return lb;
1510 }
1511 
1512 /** returns adjusted upper bound value, which is rounded for integral variable types */
1513 static
1515  SCIP_SET* set, /**< global SCIP settings */
1516  SCIP_VARTYPE vartype, /**< type of variable */
1517  SCIP_Real ub /**< upper bound to adjust */
1518  )
1519 {
1520  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1521  return SCIPsetInfinity(set);
1522  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1523  return -SCIPsetInfinity(set);
1524  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1525  return SCIPsetFeasFloor(set, ub);
1526  else if( SCIPsetIsZero(set, ub) )
1527  return 0.0;
1528  else
1529  return ub;
1530 }
1531 
1532 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1533  * bounds arrays, and optionally removes them also from the variable itself
1534  */
1536  SCIP_VAR* var, /**< problem variable */
1537  BMS_BLKMEM* blkmem, /**< block memory */
1538  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1539  SCIP_SET* set, /**< global SCIP settings */
1540  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1541  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1542  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1543  )
1544 {
1545  SCIP_Real lb;
1546  SCIP_Real ub;
1547 
1548  assert(var != NULL);
1550  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1551 
1552  lb = SCIPvarGetLbGlobal(var);
1553  ub = SCIPvarGetUbGlobal(var);
1554 
1555  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1556  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1557 
1558  /* remove implications of (fixed) binary variable */
1559  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1560  {
1561  SCIP_Bool varfixing;
1562 
1563  assert(SCIPvarIsBinary(var));
1564 
1565  varfixing = FALSE;
1566  do
1567  {
1568  SCIP_VAR** implvars;
1569  SCIP_BOUNDTYPE* impltypes;
1570  int nimpls;
1571  int i;
1572 
1573  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1574  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1575  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1576 
1577  for( i = 0; i < nimpls; i++ )
1578  {
1579  SCIP_VAR* implvar;
1580  SCIP_BOUNDTYPE impltype;
1581 
1582  implvar = implvars[i];
1583  impltype = impltypes[i];
1584  assert(implvar != var);
1585 
1586  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1587  * the following variable bound from x's variable bounds
1588  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1589  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1590  */
1591  if( impltype == SCIP_BOUNDTYPE_UPPER )
1592  {
1593  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1594  {
1595  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1596  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1597  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1598  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1599  implvar->closestvblpcount = -1;
1600  var->closestvblpcount = -1;
1601  }
1602  }
1603  else
1604  {
1605  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1606  {
1607  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1608  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1609  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1610  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1611  implvar->closestvblpcount = -1;
1612  var->closestvblpcount = -1;
1613  }
1614  }
1615  }
1616  varfixing = !varfixing;
1617  }
1618  while( varfixing == TRUE );
1619 
1620  if( removefromvar )
1621  {
1622  /* free the implications data structures */
1623  SCIPimplicsFree(&var->implics, blkmem);
1624  }
1625  }
1626 
1627  /* remove the (redundant) variable lower bounds */
1628  if( var->vlbs != NULL )
1629  {
1630  SCIP_VAR** vars;
1631  SCIP_Real* coefs;
1632  SCIP_Real* constants;
1633  int nvbds;
1634  int newnvbds;
1635  int i;
1636 
1637  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1638  vars = SCIPvboundsGetVars(var->vlbs);
1639  coefs = SCIPvboundsGetCoefs(var->vlbs);
1640  constants = SCIPvboundsGetConstants(var->vlbs);
1641 
1642  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1643  * z == ub ==> x >= b*ub + d , if b > 0
1644  * z == lb ==> x >= b*lb + d , if b < 0
1645  */
1646  newnvbds = 0;
1647  for( i = 0; i < nvbds; i++ )
1648  {
1649  SCIP_VAR* implvar;
1650  SCIP_Real coef;
1651 
1652  assert(newnvbds <= i);
1653 
1654  implvar = vars[i];
1655  assert(implvar != NULL);
1656 
1657  coef = coefs[i];
1658  assert(!SCIPsetIsZero(set, coef));
1659 
1660  /* check, if we want to remove the variable bound */
1661  if( onlyredundant )
1662  {
1663  SCIP_Real vbound;
1664 
1665  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1666  if( SCIPsetIsFeasGT(set, vbound, lb) )
1667  {
1668  /* the variable bound is not redundant: keep it */
1669  if( removefromvar )
1670  {
1671  if( newnvbds < i )
1672  {
1673  vars[newnvbds] = implvar;
1674  coefs[newnvbds] = coef;
1675  constants[newnvbds] = constants[i];
1676  }
1677  newnvbds++;
1678  }
1679  continue;
1680  }
1681  }
1682 
1683  /* remove the corresponding implication */
1684  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1685  {
1686  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1687  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1688  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1689  }
1690  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1691  {
1692  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1693  SCIPvarGetName(implvar), SCIPvarGetName(var));
1694  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1695  implvar->closestvblpcount = -1;
1696  var->closestvblpcount = -1;
1697  }
1698  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1699  {
1700  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1701  SCIPvarGetName(implvar), SCIPvarGetName(var));
1702  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1703  implvar->closestvblpcount = -1;
1704  var->closestvblpcount = -1;
1705  }
1706  }
1707 
1708  if( removefromvar )
1709  {
1710  /* update the number of variable bounds */
1711  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1712  var->closestvblpcount = -1;
1713  }
1714  }
1715 
1716  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1717  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1718  * cannot remove such variables x from z's implications.
1719  */
1720 
1721  /* remove the (redundant) variable upper bounds */
1722  if( var->vubs != NULL )
1723  {
1724  SCIP_VAR** vars;
1725  SCIP_Real* coefs;
1726  SCIP_Real* constants;
1727  int nvbds;
1728  int newnvbds;
1729  int i;
1730 
1731  nvbds = SCIPvboundsGetNVbds(var->vubs);
1732  vars = SCIPvboundsGetVars(var->vubs);
1733  coefs = SCIPvboundsGetCoefs(var->vubs);
1734  constants = SCIPvboundsGetConstants(var->vubs);
1735 
1736  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1737  * z == lb ==> x <= b*lb + d , if b > 0
1738  * z == ub ==> x <= b*ub + d , if b < 0
1739  */
1740  newnvbds = 0;
1741  for( i = 0; i < nvbds; i++ )
1742  {
1743  SCIP_VAR* implvar;
1744  SCIP_Real coef;
1745 
1746  assert(newnvbds <= i);
1747 
1748  implvar = vars[i];
1749  assert(implvar != NULL);
1750 
1751  coef = coefs[i];
1752  assert(!SCIPsetIsZero(set, coef));
1753 
1754  /* check, if we want to remove the variable bound */
1755  if( onlyredundant )
1756  {
1757  SCIP_Real vbound;
1758 
1759  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1760  if( SCIPsetIsFeasLT(set, vbound, ub) )
1761  {
1762  /* the variable bound is not redundant: keep it */
1763  if( removefromvar )
1764  {
1765  if( newnvbds < i )
1766  {
1767  vars[newnvbds] = implvar;
1768  coefs[newnvbds] = coefs[i];
1769  constants[newnvbds] = constants[i];
1770  }
1771  newnvbds++;
1772  }
1773  continue;
1774  }
1775  }
1776 
1777  /* remove the corresponding implication */
1778  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1779  {
1780  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1781  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1782  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1783  }
1784  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1785  {
1786  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1787  SCIPvarGetName(implvar), SCIPvarGetName(var));
1788  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1789  implvar->closestvblpcount = -1;
1790  var->closestvblpcount = -1;
1791  }
1792  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1793  {
1794  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1795  SCIPvarGetName(implvar), SCIPvarGetName(var));
1796  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1797  implvar->closestvblpcount = -1;
1798  var->closestvblpcount = -1;
1799  }
1800  }
1801 
1802  if( removefromvar )
1803  {
1804  /* update the number of variable bounds */
1805  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1806  var->closestvblpcount = -1;
1807  }
1808  }
1809 
1810  /* remove the variable from all cliques */
1811  if( SCIPvarIsBinary(var) )
1812  {
1813  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1814  SCIPcliquelistFree(&var->cliquelist, blkmem);
1815  }
1816 
1817  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1818  * z has no link (like in the binary case) to x
1819  */
1820 
1821  return SCIP_OKAY;
1822 }
1823 
1824 /** sets the variable name */
1825 static
1827  SCIP_VAR* var, /**< problem variable */
1828  BMS_BLKMEM* blkmem, /**< block memory */
1829  SCIP_STAT* stat, /**< problem statistics, or NULL */
1830  const char* name /**< name of variable, or NULL for automatic name creation */
1831  )
1832 {
1833  assert(blkmem != NULL);
1834  assert(var != NULL);
1835 
1836  if( name == NULL )
1837  {
1838  char s[SCIP_MAXSTRLEN];
1839 
1840  assert(stat != NULL);
1841 
1842  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1843  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1844  }
1845  else
1846  {
1847  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1848  }
1849 
1850  return SCIP_OKAY;
1851 }
1852 
1853 
1854 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1855  * with bounds zero and one is automatically converted into a binary variable
1856  */
1857 static
1859  SCIP_VAR** var, /**< pointer to variable data */
1860  BMS_BLKMEM* blkmem, /**< block memory */
1861  SCIP_SET* set, /**< global SCIP settings */
1862  SCIP_STAT* stat, /**< problem statistics */
1863  const char* name, /**< name of variable, or NULL for automatic name creation */
1864  SCIP_Real lb, /**< lower bound of variable */
1865  SCIP_Real ub, /**< upper bound of variable */
1866  SCIP_Real obj, /**< objective function value */
1867  SCIP_VARTYPE vartype, /**< type of variable */
1868  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1869  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1870  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1871  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1872  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1873  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1874  SCIP_VARDATA* vardata /**< user data for this specific variable */
1875  )
1876 {
1877  int i;
1878 
1879  assert(var != NULL);
1880  assert(blkmem != NULL);
1881  assert(stat != NULL);
1882 
1883  /* adjust bounds of variable */
1884  lb = adjustedLb(set, vartype, lb);
1885  ub = adjustedUb(set, vartype, ub);
1886 
1887  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1888  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1889  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1890  {
1891  if( vartype == SCIP_VARTYPE_INTEGER )
1892  vartype = SCIP_VARTYPE_BINARY;
1893  }
1894  else
1895  {
1896  if( vartype == SCIP_VARTYPE_BINARY )
1897  {
1898  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1899  return SCIP_INVALIDDATA;
1900  }
1901  }
1902 
1903  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1904  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1905 
1906  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1907 
1908  /* set variable's name */
1909  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1910 
1911 #ifndef NDEBUG
1912  (*var)->scip = set->scip;
1913 #endif
1914  (*var)->obj = obj;
1915  (*var)->unchangedobj = obj;
1916  (*var)->branchfactor = 1.0;
1917  (*var)->rootsol = 0.0;
1918  (*var)->bestrootsol = 0.0;
1919  (*var)->bestrootredcost = 0.0;
1920  (*var)->bestrootlpobjval = SCIP_INVALID;
1921  (*var)->relaxsol = 0.0;
1922  (*var)->nlpsol = 0.0;
1923  (*var)->primsolavg = 0.5 * (lb + ub);
1924  (*var)->conflictlb = SCIP_REAL_MIN;
1925  (*var)->conflictub = SCIP_REAL_MAX;
1926  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1927  (*var)->conflictrelaxedub = (*var)->conflictub;
1928  (*var)->lazylb = -SCIPsetInfinity(set);
1929  (*var)->lazyub = SCIPsetInfinity(set);
1930  (*var)->glbdom.holelist = NULL;
1931  (*var)->glbdom.lb = lb;
1932  (*var)->glbdom.ub = ub;
1933  (*var)->locdom.holelist = NULL;
1934  (*var)->locdom.lb = lb;
1935  (*var)->locdom.ub = ub;
1936  (*var)->varcopy = varcopy;
1937  (*var)->vardelorig = vardelorig;
1938  (*var)->vartrans = vartrans;
1939  (*var)->vardeltrans = vardeltrans;
1940  (*var)->vardata = vardata;
1941  (*var)->parentvars = NULL;
1942  (*var)->negatedvar = NULL;
1943  (*var)->vlbs = NULL;
1944  (*var)->vubs = NULL;
1945  (*var)->implics = NULL;
1946  (*var)->cliquelist = NULL;
1947  (*var)->eventfilter = NULL;
1948  (*var)->lbchginfos = NULL;
1949  (*var)->ubchginfos = NULL;
1950  (*var)->index = stat->nvaridx;
1951  (*var)->probindex = -1;
1952  (*var)->pseudocandindex = -1;
1953  (*var)->eventqueueindexobj = -1;
1954  (*var)->eventqueueindexlb = -1;
1955  (*var)->eventqueueindexub = -1;
1956  (*var)->parentvarssize = 0;
1957  (*var)->nparentvars = 0;
1958  (*var)->nuses = 0;
1959  (*var)->branchpriority = 0;
1960  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1961  (*var)->lbchginfossize = 0;
1962  (*var)->nlbchginfos = 0;
1963  (*var)->ubchginfossize = 0;
1964  (*var)->nubchginfos = 0;
1965  (*var)->conflictlbcount = 0;
1966  (*var)->conflictubcount = 0;
1967  (*var)->closestvlbidx = -1;
1968  (*var)->closestvubidx = -1;
1969  (*var)->closestvblpcount = -1;
1970  (*var)->initial = initial;
1971  (*var)->removable = removable;
1972  (*var)->deleted = FALSE;
1973  (*var)->donotmultaggr = FALSE;
1974  (*var)->vartype = vartype; /*lint !e641*/
1975  (*var)->pseudocostflag = FALSE;
1976  (*var)->eventqueueimpl = FALSE;
1977  (*var)->deletable = FALSE;
1978  (*var)->delglobalstructs = FALSE;
1979  (*var)->relaxationonly = FALSE;
1980 
1981  for( i = 0; i < NLOCKTYPES; i++ )
1982  {
1983  (*var)->nlocksdown[i] = 0;
1984  (*var)->nlocksup[i] = 0;
1985  }
1986 
1987  stat->nvaridx++;
1988 
1989  /* create branching and inference history entries */
1990  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1991  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1992 
1993  /* the value based history is only created on demand */
1994  (*var)->valuehistory = NULL;
1995 
1996  return SCIP_OKAY;
1997 }
1998 
1999 /** creates and captures an original problem variable; an integer variable with bounds
2000  * zero and one is automatically converted into a binary variable
2001  */
2003  SCIP_VAR** var, /**< pointer to variable data */
2004  BMS_BLKMEM* blkmem, /**< block memory */
2005  SCIP_SET* set, /**< global SCIP settings */
2006  SCIP_STAT* stat, /**< problem statistics */
2007  const char* name, /**< name of variable, or NULL for automatic name creation */
2008  SCIP_Real lb, /**< lower bound of variable */
2009  SCIP_Real ub, /**< upper bound of variable */
2010  SCIP_Real obj, /**< objective function value */
2011  SCIP_VARTYPE vartype, /**< type of variable */
2012  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2013  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2014  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2015  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2016  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2017  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2018  SCIP_VARDATA* vardata /**< user data for this specific variable */
2019  )
2020 {
2021  assert(var != NULL);
2022  assert(blkmem != NULL);
2023  assert(stat != NULL);
2024 
2025  /* create variable */
2026  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2027  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2028 
2029  /* set variable status and data */
2030  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2031  (*var)->data.original.origdom.holelist = NULL;
2032  (*var)->data.original.origdom.lb = lb;
2033  (*var)->data.original.origdom.ub = ub;
2034  (*var)->data.original.transvar = NULL;
2035 
2036  /* capture variable */
2037  SCIPvarCapture(*var);
2038 
2039  return SCIP_OKAY;
2040 }
2041 
2042 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2043  * zero and one is automatically converted into a binary variable
2044  */
2046  SCIP_VAR** var, /**< pointer to variable data */
2047  BMS_BLKMEM* blkmem, /**< block memory */
2048  SCIP_SET* set, /**< global SCIP settings */
2049  SCIP_STAT* stat, /**< problem statistics */
2050  const char* name, /**< name of variable, or NULL for automatic name creation */
2051  SCIP_Real lb, /**< lower bound of variable */
2052  SCIP_Real ub, /**< upper bound of variable */
2053  SCIP_Real obj, /**< objective function value */
2054  SCIP_VARTYPE vartype, /**< type of variable */
2055  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2056  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2057  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2058  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2059  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2060  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2061  SCIP_VARDATA* vardata /**< user data for this specific variable */
2062  )
2063 {
2064  assert(var != NULL);
2065  assert(blkmem != NULL);
2066 
2067  /* create variable */
2068  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2069  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2070 
2071  /* create event filter for transformed variable */
2072  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2073 
2074  /* set variable status and data */
2075  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2076 
2077  /* capture variable */
2078  SCIPvarCapture(*var);
2079 
2080  return SCIP_OKAY;
2081 }
2082 
2083 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2084  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2085  * copied at all
2086  */
2088  SCIP_VAR** var, /**< pointer to store the target variable */
2089  BMS_BLKMEM* blkmem, /**< block memory */
2090  SCIP_SET* set, /**< global SCIP settings */
2091  SCIP_STAT* stat, /**< problem statistics */
2092  SCIP* sourcescip, /**< source SCIP data structure */
2093  SCIP_VAR* sourcevar, /**< source variable */
2094  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2095  * target variables */
2096  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2097  * target constraints */
2098  SCIP_Bool global /**< should global or local bounds be used? */
2099  )
2100 {
2101  SCIP_VARDATA* targetdata;
2102  SCIP_RESULT result;
2103  SCIP_Real lb;
2104  SCIP_Real ub;
2105 
2106  assert(set != NULL);
2107  assert(blkmem != NULL);
2108  assert(stat != NULL);
2109  assert(sourcescip != NULL);
2110  assert(sourcevar != NULL);
2111  assert(var != NULL);
2112  assert(set->stage == SCIP_STAGE_PROBLEM);
2113  assert(varmap != NULL);
2114  assert(consmap != NULL);
2115 
2116  /** @todo copy hole lists */
2117  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2118  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2119 
2120  result = SCIP_DIDNOTRUN;
2121  targetdata = NULL;
2122 
2123  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2124  {
2125  lb = SCIPvarGetLbOriginal(sourcevar);
2126  ub = SCIPvarGetUbOriginal(sourcevar);
2127  }
2128  else
2129  {
2130  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2131  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2132  }
2133 
2134  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2135  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2136  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2137  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2138  NULL, NULL, NULL, NULL, NULL) );
2139  assert(*var != NULL);
2140 
2141  /* directly copy donotmultaggr flag */
2142  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2143 
2144  /* insert variable into mapping between source SCIP and the target SCIP */
2145  assert(!SCIPhashmapExists(varmap, sourcevar));
2146  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2147 
2148  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2149  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2150  {
2151  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2152  varmap, consmap, (*var), &targetdata, &result) );
2153 
2154  /* evaluate result */
2155  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2156  {
2157  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2158  return SCIP_INVALIDRESULT;
2159  }
2160 
2161  assert(targetdata == NULL || result == SCIP_SUCCESS);
2162 
2163  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2164  if( result == SCIP_SUCCESS )
2165  {
2166  (*var)->varcopy = sourcevar->varcopy;
2167  (*var)->vardelorig = sourcevar->vardelorig;
2168  (*var)->vartrans = sourcevar->vartrans;
2169  (*var)->vardeltrans = sourcevar->vardeltrans;
2170  (*var)->vardata = targetdata;
2171  }
2172  }
2173 
2174  /* we initialize histories of the variables by copying the source variable-information */
2175  if( set->history_allowtransfer )
2176  {
2177  SCIPvarMergeHistories((*var), sourcevar, stat);
2178  }
2179 
2180  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2181  * methods
2182  */
2183  if( result == SCIP_SUCCESS )
2184  {
2185  (*var)->varcopy = sourcevar->varcopy;
2186  (*var)->vardelorig = sourcevar->vardelorig;
2187  (*var)->vartrans = sourcevar->vartrans;
2188  (*var)->vardeltrans = sourcevar->vardeltrans;
2189  (*var)->vardata = targetdata;
2190  }
2191 
2192  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2193 
2194  return SCIP_OKAY;
2195 }
2196 
2197 /** parse given string for a SCIP_Real bound */
2198 static
2200  SCIP_SET* set, /**< global SCIP settings */
2201  const char* str, /**< string to parse */
2202  SCIP_Real* value, /**< pointer to store the parsed value */
2203  char** endptr /**< pointer to store the final string position if successfully parsed */
2204  )
2205 {
2206  /* first check for infinity value */
2207  if( strncmp(str, "+inf", 4) == 0 )
2208  {
2209  *value = SCIPsetInfinity(set);
2210  (*endptr) = (char*)str + 4;
2211  }
2212  else if( strncmp(str, "-inf", 4) == 0 )
2213  {
2214  *value = -SCIPsetInfinity(set);
2215  (*endptr) = (char*)str + 4;
2216  }
2217  else
2218  {
2219  if( !SCIPstrToRealValue(str, value, endptr) )
2220  {
2221  SCIPerrorMessage("expected value: %s.\n", str);
2222  return SCIP_READERROR;
2223  }
2224  }
2225 
2226  return SCIP_OKAY;
2227 }
2228 
2229 /** parse the characters as bounds */
2230 static
2232  SCIP_SET* set, /**< global SCIP settings */
2233  const char* str, /**< string to parse */
2234  char* type, /**< bound type (global, local, or lazy) */
2235  SCIP_Real* lb, /**< pointer to store the lower bound */
2236  SCIP_Real* ub, /**< pointer to store the upper bound */
2237  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2238  )
2239 {
2240  char token[SCIP_MAXSTRLEN];
2241  char* tmpend;
2242 
2243  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2244 
2245  /* get bound type */
2246  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2247  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2248  {
2249  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2250  *endptr = NULL;
2251  return SCIP_OKAY;
2252  }
2253 
2254  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2255 
2256  /* get lower bound */
2257  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2258  str = *endptr;
2259  SCIP_CALL( parseValue(set, token, lb, &tmpend) );
2260 
2261  /* get upper bound */
2262  SCIP_CALL( parseValue(set, str, ub, endptr) );
2263 
2264  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2265 
2266  /* skip end of bounds */
2267  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2268  ++(*endptr);
2269 
2270  return SCIP_OKAY;
2271 }
2272 
2273 /** parses a given string for a variable informations */
2274 static
2276  SCIP_SET* set, /**< global SCIP settings */
2277  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2278  const char* str, /**< string to parse */
2279  char* name, /**< pointer to store the variable name */
2280  SCIP_Real* lb, /**< pointer to store the lower bound */
2281  SCIP_Real* ub, /**< pointer to store the upper bound */
2282  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2283  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2284  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2285  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2286  SCIP_Bool local, /**< should the local bound be applied */
2287  char** endptr, /**< pointer to store the final string position if successfully */
2288  SCIP_Bool* success /**< pointer store if the paring process was successful */
2289  )
2290 {
2291  SCIP_Real parsedlb;
2292  SCIP_Real parsedub;
2293  char token[SCIP_MAXSTRLEN];
2294  char* strptr;
2295  int i;
2296 
2297  assert(lb != NULL);
2298  assert(ub != NULL);
2299  assert(obj != NULL);
2300  assert(vartype != NULL);
2301  assert(lazylb != NULL);
2302  assert(lazyub != NULL);
2303  assert(success != NULL);
2304 
2305  (*success) = TRUE;
2306 
2307  /* copy variable type */
2308  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2309  assert(str != *endptr);
2310  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2311 
2312  /* get variable type */
2313  if( strncmp(token, "binary", 3) == 0 )
2314  (*vartype) = SCIP_VARTYPE_BINARY;
2315  else if( strncmp(token, "integer", 3) == 0 )
2316  (*vartype) = SCIP_VARTYPE_INTEGER;
2317  else if( strncmp(token, "implicit", 3) == 0 )
2318  (*vartype) = SCIP_VARTYPE_IMPLINT;
2319  else if( strncmp(token, "continuous", 3) == 0 )
2320  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2321  else
2322  {
2323  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2324  (*success) = FALSE;
2325  return SCIP_OKAY;
2326  }
2327 
2328  /* move string pointer behind variable type */
2329  str = *endptr;
2330 
2331  /* get variable name */
2332  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2333  assert(endptr != NULL);
2334  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2335 
2336  /* move string pointer behind variable name */
2337  str = *endptr;
2338 
2339  /* cut out objective coefficient */
2340  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2341 
2342  /* move string pointer behind objective coefficient */
2343  str = *endptr;
2344 
2345  /* get objective coefficient */
2346  if( !SCIPstrToRealValue(token, obj, endptr) )
2347  {
2348  *endptr = NULL;
2349  return SCIP_READERROR;
2350  }
2351 
2352  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2353 
2354  /* parse global/original bounds */
2355  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2356  if ( *endptr == NULL )
2357  {
2358  SCIPerrorMessage("Expected bound type: %s.\n", token);
2359  return SCIP_READERROR;
2360  }
2361  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2362 
2363  /* initialize the lazy bound */
2364  *lazylb = -SCIPsetInfinity(set);
2365  *lazyub = SCIPsetInfinity(set);
2366 
2367  /* store pointer */
2368  strptr = *endptr;
2369 
2370  /* possibly parse optional local and lazy bounds */
2371  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2372  {
2373  /* start after previous bounds */
2374  strptr = *endptr;
2375 
2376  /* parse global bounds */
2377  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2378 
2379  /* stop if parsing of bounds failed */
2380  if( *endptr == NULL )
2381  break;
2382 
2383  if( strncmp(token, "local", 5) == 0 && local )
2384  {
2385  *lb = parsedlb;
2386  *ub = parsedub;
2387  }
2388  else if( strncmp(token, "lazy", 4) == 0 )
2389  {
2390  *lazylb = parsedlb;
2391  *lazyub = parsedub;
2392  }
2393  }
2394 
2395  /* restore pointer */
2396  if ( *endptr == NULL )
2397  *endptr = strptr;
2398 
2399  /* check bounds for binary variables */
2400  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2401  {
2402  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2403  {
2404  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2405  return SCIP_READERROR;
2406  }
2407  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2408  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2409  {
2410  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2411  return SCIP_READERROR;
2412  }
2413  }
2414 
2415  return SCIP_OKAY;
2416 }
2417 
2418 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2419  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2420  * integer variable with bounds zero and one is automatically converted into a binary variable
2421  */
2423  SCIP_VAR** var, /**< pointer to variable data */
2424  BMS_BLKMEM* blkmem, /**< block memory */
2425  SCIP_SET* set, /**< global SCIP settings */
2426  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2427  SCIP_STAT* stat, /**< problem statistics */
2428  const char* str, /**< string to parse */
2429  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2430  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2431  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2432  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2433  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2434  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2435  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2436  char** endptr, /**< pointer to store the final string position if successfully */
2437  SCIP_Bool* success /**< pointer store if the paring process was successful */
2438  )
2439 {
2440  char name[SCIP_MAXSTRLEN];
2441  SCIP_Real lb;
2442  SCIP_Real ub;
2443  SCIP_Real obj;
2444  SCIP_VARTYPE vartype;
2445  SCIP_Real lazylb;
2446  SCIP_Real lazyub;
2447 
2448  assert(var != NULL);
2449  assert(blkmem != NULL);
2450  assert(stat != NULL);
2451  assert(endptr != NULL);
2452  assert(success != NULL);
2453 
2454  /* parse string in cip format for variable information */
2455  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2456 
2457  if( *success )
2458  {
2459  /* create variable */
2460  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2461  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2462 
2463  /* set variable status and data */
2464  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2465  (*var)->data.original.origdom.holelist = NULL;
2466  (*var)->data.original.origdom.lb = lb;
2467  (*var)->data.original.origdom.ub = ub;
2468  (*var)->data.original.transvar = NULL;
2469 
2470  /* set lazy status of variable bounds */
2471  (*var)->lazylb = lazylb;
2472  (*var)->lazyub = lazyub;
2473 
2474  /* capture variable */
2475  SCIPvarCapture(*var);
2476  }
2477 
2478  return SCIP_OKAY;
2479 }
2480 
2481 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2482  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2483  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2484  * variable
2485  */
2487  SCIP_VAR** var, /**< pointer to variable data */
2488  BMS_BLKMEM* blkmem, /**< block memory */
2489  SCIP_SET* set, /**< global SCIP settings */
2490  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2491  SCIP_STAT* stat, /**< problem statistics */
2492  const char* str, /**< string to parse */
2493  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2494  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2495  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2496  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2497  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2498  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2499  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2500  char** endptr, /**< pointer to store the final string position if successfully */
2501  SCIP_Bool* success /**< pointer store if the paring process was successful */
2502  )
2503 {
2504  char name[SCIP_MAXSTRLEN];
2505  SCIP_Real lb;
2506  SCIP_Real ub;
2507  SCIP_Real obj;
2508  SCIP_VARTYPE vartype;
2509  SCIP_Real lazylb;
2510  SCIP_Real lazyub;
2511 
2512  assert(var != NULL);
2513  assert(blkmem != NULL);
2514  assert(endptr != NULL);
2515  assert(success != NULL);
2516 
2517  /* parse string in cip format for variable information */
2518  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2519 
2520  if( *success )
2521  {
2522  /* create variable */
2523  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2524  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2525 
2526  /* create event filter for transformed variable */
2527  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2528 
2529  /* set variable status and data */
2530  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2531 
2532  /* set lazy status of variable bounds */
2533  (*var)->lazylb = lazylb;
2534  (*var)->lazyub = lazyub;
2535 
2536  /* capture variable */
2537  SCIPvarCapture(*var);
2538  }
2539 
2540  return SCIP_OKAY;
2541 }
2542 
2543 /** ensures, that parentvars array of var can store at least num entries */
2544 static
2546  SCIP_VAR* var, /**< problem variable */
2547  BMS_BLKMEM* blkmem, /**< block memory */
2548  SCIP_SET* set, /**< global SCIP settings */
2549  int num /**< minimum number of entries to store */
2550  )
2551 {
2552  assert(var->nparentvars <= var->parentvarssize);
2553 
2554  if( num > var->parentvarssize )
2555  {
2556  int newsize;
2557 
2558  newsize = SCIPsetCalcMemGrowSize(set, num);
2559  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2560  var->parentvarssize = newsize;
2561  }
2562  assert(num <= var->parentvarssize);
2563 
2564  return SCIP_OKAY;
2565 }
2566 
2567 /** adds variable to parent list of a variable and captures parent variable */
2568 static
2570  SCIP_VAR* var, /**< variable to add parent to */
2571  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2572  SCIP_SET* set, /**< global SCIP settings */
2573  SCIP_VAR* parentvar /**< parent variable to add */
2574  )
2575 {
2576  assert(var != NULL);
2577  assert(parentvar != NULL);
2578 
2579  /* the direct original counterpart must be stored as first parent */
2580  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2581 
2582  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2583  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2584 
2585  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2586 
2587  var->parentvars[var->nparentvars] = parentvar;
2588  var->nparentvars++;
2589 
2590  SCIPvarCapture(parentvar);
2591 
2592  return SCIP_OKAY;
2593 }
2594 
2595 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2596 static
2598  SCIP_VAR** var, /**< pointer to variable */
2599  BMS_BLKMEM* blkmem, /**< block memory */
2600  SCIP_SET* set, /**< global SCIP settings */
2601  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2602  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2603  )
2604 {
2605  SCIP_VAR* parentvar;
2606  int i;
2607 
2608  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2609 
2610  /* release the parent variables and remove the link from the parent variable to the child */
2611  for( i = 0; i < (*var)->nparentvars; ++i )
2612  {
2613  assert((*var)->parentvars != NULL);
2614  parentvar = (*var)->parentvars[i];
2615  assert(parentvar != NULL);
2616 
2617  switch( SCIPvarGetStatus(parentvar) )
2618  {
2620  assert(parentvar->data.original.transvar == *var);
2621  assert(&parentvar->data.original.transvar != var);
2622  parentvar->data.original.transvar = NULL;
2623  break;
2624 
2626  assert(parentvar->data.aggregate.var == *var);
2627  assert(&parentvar->data.aggregate.var != var);
2628  parentvar->data.aggregate.var = NULL;
2629  break;
2630 
2631 #if 0
2632  /* The following code is unclear: should the current variable be removed from its parents? */
2634  assert(parentvar->data.multaggr.vars != NULL);
2635  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2636  {}
2637  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2638  if( v < parentvar->data.multaggr.nvars-1 )
2639  {
2640  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2641  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2642  }
2643  parentvar->data.multaggr.nvars--;
2644  break;
2645 #endif
2646 
2648  assert(parentvar->negatedvar == *var);
2649  assert((*var)->negatedvar == parentvar);
2650  parentvar->negatedvar = NULL;
2651  (*var)->negatedvar = NULL;
2652  break;
2653 
2654  default:
2655  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2656  return SCIP_INVALIDDATA;
2657  } /*lint !e788*/
2658 
2659  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2660  }
2661 
2662  /* free parentvars array */
2663  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2664 
2665  return SCIP_OKAY;
2666 }
2667 
2668 /** frees a variable */
2669 static
2671  SCIP_VAR** var, /**< pointer to variable */
2672  BMS_BLKMEM* blkmem, /**< block memory */
2673  SCIP_SET* set, /**< global SCIP settings */
2674  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2675  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2676  )
2677 {
2678  assert(var != NULL);
2679  assert(*var != NULL);
2680  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2681  assert((*var)->nuses == 0);
2682  assert((*var)->probindex == -1);
2683  assert((*var)->nlocksup[SCIP_LOCKTYPE_MODEL] == 0);
2684  assert((*var)->nlocksdown[SCIP_LOCKTYPE_MODEL] == 0);
2685 
2686  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2687 
2688  switch( SCIPvarGetStatus(*var) )
2689  {
2691  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2692  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2693  assert((*var)->data.original.origdom.holelist == NULL);
2694  break;
2695  case SCIP_VARSTATUS_LOOSE:
2696  break;
2697  case SCIP_VARSTATUS_COLUMN:
2698  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2699  break;
2700  case SCIP_VARSTATUS_FIXED:
2702  break;
2704  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2705  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2706  break;
2708  break;
2709  default:
2710  SCIPerrorMessage("unknown variable status\n");
2711  return SCIP_INVALIDDATA;
2712  }
2713 
2714  /* release all parent variables and free the parentvars array */
2715  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2716 
2717  /* free user data */
2719  {
2720  if( (*var)->vardelorig != NULL )
2721  {
2722  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2723  }
2724  }
2725  else
2726  {
2727  if( (*var)->vardeltrans != NULL )
2728  {
2729  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2730  }
2731  }
2732 
2733  /* free event filter */
2734  if( (*var)->eventfilter != NULL )
2735  {
2736  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2737  }
2738  assert((*var)->eventfilter == NULL);
2739 
2740  /* free hole lists */
2741  holelistFree(&(*var)->glbdom.holelist, blkmem);
2742  holelistFree(&(*var)->locdom.holelist, blkmem);
2743  assert((*var)->glbdom.holelist == NULL);
2744  assert((*var)->locdom.holelist == NULL);
2745 
2746  /* free variable bounds data structures */
2747  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2748  SCIPvboundsFree(&(*var)->vubs, blkmem);
2749 
2750  /* free implications data structures */
2751  SCIPimplicsFree(&(*var)->implics, blkmem);
2752 
2753  /* free clique list data structures */
2754  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2755 
2756  /* free bound change information arrays */
2757  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2758  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2759 
2760  /* free branching and inference history entries */
2761  SCIPhistoryFree(&(*var)->history, blkmem);
2762  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2763  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2764 
2765  /* free variable data structure */
2766  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2767  BMSfreeBlockMemory(blkmem, var);
2768 
2769  return SCIP_OKAY;
2770 }
2771 
2772 /** increases usage counter of variable */
2773 void SCIPvarCapture(
2774  SCIP_VAR* var /**< variable */
2775  )
2776 {
2777  assert(var != NULL);
2778  assert(var->nuses >= 0);
2779 
2780  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2781  var->nuses++;
2782 }
2783 
2784 /** decreases usage counter of variable, and frees memory if necessary */
2786  SCIP_VAR** var, /**< pointer to variable */
2787  BMS_BLKMEM* blkmem, /**< block memory */
2788  SCIP_SET* set, /**< global SCIP settings */
2789  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2790  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2791  )
2792 {
2793  assert(var != NULL);
2794  assert(*var != NULL);
2795  assert((*var)->nuses >= 1);
2796  assert(blkmem != NULL);
2797  assert((*var)->scip == set->scip);
2798 
2799  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2800  (*var)->nuses--;
2801  if( (*var)->nuses == 0 )
2802  {
2803  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2804  }
2805 
2806  *var = NULL;
2807 
2808  return SCIP_OKAY;
2809 }
2810 
2811 /** change variable name */
2813  SCIP_VAR* var, /**< problem variable */
2814  BMS_BLKMEM* blkmem, /**< block memory */
2815  const char* name /**< name of variable */
2816  )
2817 {
2818  assert(name != NULL);
2819 
2820  /* remove old variable name */
2821  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2822 
2823  /* set new variable name */
2824  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2825 
2826  return SCIP_OKAY;
2827 }
2828 
2829 /** initializes variable data structure for solving */
2830 void SCIPvarInitSolve(
2831  SCIP_VAR* var /**< problem variable */
2832  )
2833 {
2834  assert(var != NULL);
2835 
2837  var->conflictlbcount = 0;
2838  var->conflictubcount = 0;
2839 }
2840 
2841 /** outputs the given bounds into the file stream */
2842 static
2843 void printBounds(
2844  SCIP_SET* set, /**< global SCIP settings */
2845  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2846  FILE* file, /**< output file (or NULL for standard output) */
2847  SCIP_Real lb, /**< lower bound */
2848  SCIP_Real ub, /**< upper bound */
2849  const char* name /**< bound type name */
2850  )
2851 {
2852  assert(set != NULL);
2853 
2854  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2855  if( SCIPsetIsInfinity(set, lb) )
2856  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2857  else if( SCIPsetIsInfinity(set, -lb) )
2858  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2859  else
2860  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2861  if( SCIPsetIsInfinity(set, ub) )
2862  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2863  else if( SCIPsetIsInfinity(set, -ub) )
2864  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2865  else
2866  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2867 }
2868 
2869 /** prints hole list to file stream */
2870 static
2871 void printHolelist(
2872  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2873  FILE* file, /**< output file (or NULL for standard output) */
2874  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2875  const char* name /**< hole type name */
2876  )
2877 { /*lint --e{715}*/
2878  SCIP_Real left;
2879  SCIP_Real right;
2880 
2881  if( holelist == NULL )
2882  return;
2883 
2884  left = SCIPholelistGetLeft(holelist);
2885  right = SCIPholelistGetRight(holelist);
2886 
2887  /* display first hole */
2888  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2889  holelist = SCIPholelistGetNext(holelist);
2890 
2891  while(holelist != NULL )
2892  {
2893  left = SCIPholelistGetLeft(holelist);
2894  right = SCIPholelistGetRight(holelist);
2895 
2896  /* display hole */
2897  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2898 
2899  /* get next hole */
2900  holelist = SCIPholelistGetNext(holelist);
2901  }
2902 }
2903 
2904 /** outputs variable information into file stream */
2906  SCIP_VAR* var, /**< problem variable */
2907  SCIP_SET* set, /**< global SCIP settings */
2908  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2909  FILE* file /**< output file (or NULL for standard output) */
2910  )
2911 {
2912  SCIP_HOLELIST* holelist;
2913  SCIP_Real lb;
2914  SCIP_Real ub;
2915  int i;
2916 
2917  assert(var != NULL);
2918  assert(var->scip == set->scip);
2919 
2920  /* type of variable */
2921  switch( SCIPvarGetType(var) )
2922  {
2923  case SCIP_VARTYPE_BINARY:
2924  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2925  break;
2926  case SCIP_VARTYPE_INTEGER:
2927  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2928  break;
2929  case SCIP_VARTYPE_IMPLINT:
2930  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2931  break;
2933  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2934  break;
2935  default:
2936  SCIPerrorMessage("unknown variable type\n");
2937  SCIPABORT();
2938  return SCIP_ERROR; /*lint !e527*/
2939  }
2940 
2941  /* name */
2942  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2943 
2944  /* objective value */
2945  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2946 
2947  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2948  if( !SCIPvarIsTransformed(var) )
2949  {
2950  /* output original bound */
2951  lb = SCIPvarGetLbOriginal(var);
2952  ub = SCIPvarGetUbOriginal(var);
2953  printBounds(set, messagehdlr, file, lb, ub, "original 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  holelist = SCIPvarGetHolelistOriginal(var);
2964  printHolelist(messagehdlr, file, holelist, "original holes");
2965  }
2966  else
2967  {
2968  /* output global bound */
2969  lb = SCIPvarGetLbGlobal(var);
2970  ub = SCIPvarGetUbGlobal(var);
2971  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2972 
2973  /* output local bound */
2974  lb = SCIPvarGetLbLocal(var);
2975  ub = SCIPvarGetUbLocal(var);
2976  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2977 
2978  /* output lazy bound */
2979  lb = SCIPvarGetLbLazy(var);
2980  ub = SCIPvarGetUbLazy(var);
2981 
2982  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2983  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2984  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2985 
2986  /* global hole list */
2987  holelist = SCIPvarGetHolelistGlobal(var);
2988  printHolelist(messagehdlr, file, holelist, "global holes");
2989 
2990  /* local hole list */
2991  holelist = SCIPvarGetHolelistLocal(var);
2992  printHolelist(messagehdlr, file, holelist, "local holes");
2993  }
2994 
2995  /* fixings and aggregations */
2996  switch( SCIPvarGetStatus(var) )
2997  {
2999  case SCIP_VARSTATUS_LOOSE:
3000  case SCIP_VARSTATUS_COLUMN:
3001  break;
3002 
3003  case SCIP_VARSTATUS_FIXED:
3004  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
3005  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
3006  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
3007  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
3008  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
3009  else
3010  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
3011  break;
3012 
3014  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3015  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
3016  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
3017  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
3018  break;
3019 
3021  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3022  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3023  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3024  for( i = 0; i < var->data.multaggr.nvars; ++i )
3025  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3026  break;
3027 
3029  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3030  break;
3031 
3032  default:
3033  SCIPerrorMessage("unknown variable status\n");
3034  SCIPABORT();
3035  return SCIP_ERROR; /*lint !e527*/
3036  }
3037 
3038  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3039 
3040  return SCIP_OKAY;
3041 }
3042 
3043 /** issues a VARUNLOCKED event on the given variable */
3044 static
3046  SCIP_VAR* var, /**< problem variable to change */
3047  BMS_BLKMEM* blkmem, /**< block memory */
3048  SCIP_SET* set, /**< global SCIP settings */
3049  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3050  )
3051 {
3052  SCIP_EVENT* event;
3053 
3054  assert(var != NULL);
3055  assert(var->nlocksdown[SCIP_LOCKTYPE_MODEL] <= 1 && var->nlocksup[SCIP_LOCKTYPE_MODEL] <= 1);
3056  assert(var->scip == set->scip);
3057 
3058  /* issue VARUNLOCKED event on variable */
3059  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3060  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3061 
3062  return SCIP_OKAY;
3063 }
3064 
3065 /** modifies lock numbers for rounding */
3067  SCIP_VAR* var, /**< problem variable */
3068  BMS_BLKMEM* blkmem, /**< block memory */
3069  SCIP_SET* set, /**< global SCIP settings */
3070  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3071  SCIP_LOCKTYPE locktype, /**< type of the variable locks */
3072  int addnlocksdown, /**< increase in number of rounding down locks */
3073  int addnlocksup /**< increase in number of rounding up locks */
3074  )
3075 {
3076  SCIP_VAR* lockvar;
3077 
3078  assert(var != NULL);
3079  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568*/
3080  assert(var->nlocksup[locktype] >= 0);
3081  assert(var->nlocksdown[locktype] >= 0);
3082  assert(var->scip == set->scip);
3083 
3084  if( addnlocksdown == 0 && addnlocksup == 0 )
3085  return SCIP_OKAY;
3086 
3087 #ifdef SCIP_DEBUG
3088  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d, type=%u)\n",
3089  addnlocksdown, addnlocksup, var->name, var->nlocksdown[locktype], var->nlocksup[locktype], locktype);
3090 #endif
3091 
3092  lockvar = var;
3093 
3094  while( TRUE ) /*lint !e716 */
3095  {
3096  assert(lockvar != NULL);
3097 
3098  switch( SCIPvarGetStatus(lockvar) )
3099  {
3101  if( lockvar->data.original.transvar != NULL )
3102  {
3103  lockvar = lockvar->data.original.transvar;
3104  break;
3105  }
3106  else
3107  {
3108  lockvar->nlocksdown[locktype] += addnlocksdown;
3109  lockvar->nlocksup[locktype] += addnlocksup;
3110 
3111  assert(lockvar->nlocksdown[locktype] >= 0);
3112  assert(lockvar->nlocksup[locktype] >= 0);
3113 
3114  return SCIP_OKAY;
3115  }
3116  case SCIP_VARSTATUS_LOOSE:
3117  case SCIP_VARSTATUS_COLUMN:
3118  case SCIP_VARSTATUS_FIXED:
3119  lockvar->nlocksdown[locktype] += addnlocksdown;
3120  lockvar->nlocksup[locktype] += addnlocksup;
3121 
3122  assert(lockvar->nlocksdown[locktype] >= 0);
3123  assert(lockvar->nlocksup[locktype] >= 0);
3124 
3125  if( locktype == SCIP_LOCKTYPE_MODEL && lockvar->nlocksdown[locktype] <= 1
3126  && lockvar->nlocksup[locktype] <= 1 )
3127  {
3128  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3129  }
3130 
3131  return SCIP_OKAY;
3133  if( lockvar->data.aggregate.scalar < 0.0 )
3134  {
3135  int tmp = addnlocksup;
3136 
3137  addnlocksup = addnlocksdown;
3138  addnlocksdown = tmp;
3139  }
3140 
3141  lockvar = lockvar->data.aggregate.var;
3142  break;
3144  {
3145  int v;
3146 
3147  assert(!lockvar->donotmultaggr);
3148 
3149  lockvar->nlocksdown[locktype] += addnlocksdown;
3150  lockvar->nlocksup[locktype] += addnlocksup;
3151 
3152  assert(lockvar->nlocksdown[locktype] >= 0);
3153  assert(lockvar->nlocksup[locktype] >= 0);
3154 
3155  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3156  {
3157  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3158  {
3159  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksdown,
3160  addnlocksup) );
3161  }
3162  else
3163  {
3164  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, locktype, addnlocksup,
3165  addnlocksdown) );
3166  }
3167  }
3168  return SCIP_OKAY;
3169  }
3171  {
3172  int tmp = addnlocksup;
3173 
3174  assert(lockvar->negatedvar != NULL);
3175  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3176  assert(lockvar->negatedvar->negatedvar == lockvar);
3177 
3178  addnlocksup = addnlocksdown;
3179  addnlocksdown = tmp;
3180 
3181  lockvar = lockvar->negatedvar;
3182  break;
3183  }
3184  default:
3185  SCIPerrorMessage("unknown variable status\n");
3186  return SCIP_INVALIDDATA;
3187  }
3188  }
3189 }
3190 
3191 /** gets number of locks for rounding down of a special type */
3193  SCIP_VAR* var, /**< problem variable */
3194  SCIP_LOCKTYPE locktype /**< type of variable locks */
3195  )
3196 {
3197  int nlocks;
3198  int i;
3199 
3200  assert(var != NULL);
3201  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568*/
3202  assert(var->nlocksdown[locktype] >= 0);
3203 
3204  switch( SCIPvarGetStatus(var) )
3205  {
3207  if( var->data.original.transvar != NULL )
3208  return SCIPvarGetNLocksDownType(var->data.original.transvar, locktype);
3209  else
3210  return var->nlocksdown[locktype];
3211 
3212  case SCIP_VARSTATUS_LOOSE:
3213  case SCIP_VARSTATUS_COLUMN:
3214  case SCIP_VARSTATUS_FIXED:
3215  return var->nlocksdown[locktype];
3216 
3218  if( var->data.aggregate.scalar > 0.0 )
3219  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3220  else
3221  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3222 
3224  assert(!var->donotmultaggr);
3225  nlocks = 0;
3226  for( i = 0; i < var->data.multaggr.nvars; ++i )
3227  {
3228  if( var->data.multaggr.scalars[i] > 0.0 )
3229  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3230  else
3231  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3232  }
3233  return nlocks;
3234 
3236  assert(var->negatedvar != NULL);
3238  assert(var->negatedvar->negatedvar == var);
3239  return SCIPvarGetNLocksUpType(var->negatedvar, locktype);
3240 
3241  default:
3242  SCIPerrorMessage("unknown variable status\n");
3243  SCIPABORT();
3244  return INT_MAX; /*lint !e527*/
3245  }
3246 }
3247 
3248 /** gets number of locks for rounding up of a special type */
3250  SCIP_VAR* var, /**< problem variable */
3251  SCIP_LOCKTYPE locktype /**< type of variable locks */
3252  )
3253 {
3254  int nlocks;
3255  int i;
3256 
3257  assert(var != NULL);
3258  assert((int)locktype >= 0 && (int)locktype < (int)NLOCKTYPES); /*lint !e685 !e568*/
3259  assert(var->nlocksup[locktype] >= 0);
3260 
3261  switch( SCIPvarGetStatus(var) )
3262  {
3264  if( var->data.original.transvar != NULL )
3265  return SCIPvarGetNLocksUpType(var->data.original.transvar, locktype);
3266  else
3267  return var->nlocksup[locktype];
3268 
3269  case SCIP_VARSTATUS_LOOSE:
3270  case SCIP_VARSTATUS_COLUMN:
3271  case SCIP_VARSTATUS_FIXED:
3272  return var->nlocksup[locktype];
3273 
3275  if( var->data.aggregate.scalar > 0.0 )
3276  return SCIPvarGetNLocksUpType(var->data.aggregate.var, locktype);
3277  else
3278  return SCIPvarGetNLocksDownType(var->data.aggregate.var, locktype);
3279 
3281  assert(!var->donotmultaggr);
3282  nlocks = 0;
3283  for( i = 0; i < var->data.multaggr.nvars; ++i )
3284  {
3285  if( var->data.multaggr.scalars[i] > 0.0 )
3286  nlocks += SCIPvarGetNLocksUpType(var->data.multaggr.vars[i], locktype);
3287  else
3288  nlocks += SCIPvarGetNLocksDownType(var->data.multaggr.vars[i], locktype);
3289  }
3290  return nlocks;
3291 
3293  assert(var->negatedvar != NULL);
3295  assert(var->negatedvar->negatedvar == var);
3296  return SCIPvarGetNLocksDownType(var->negatedvar, locktype);
3297 
3298  default:
3299  SCIPerrorMessage("unknown variable status\n");
3300  SCIPABORT();
3301  return INT_MAX; /*lint !e527*/
3302  }
3303 }
3304 
3305 /** gets number of locks for rounding down
3306  *
3307  * @note This method will always return variable locks of type model
3308  *
3309  * @note It is recommented to use SCIPvarGetNLocksDownType()
3310  */
3312  SCIP_VAR* var /**< problem variable */
3313  )
3314 {
3316 }
3317 
3318 /** gets number of locks for rounding up
3319  *
3320  * @note This method will always return variable locks of type model
3321  *
3322  * @note It is recommented to use SCIPvarGetNLocksUpType()
3323  */
3324 int SCIPvarGetNLocksUp(
3325  SCIP_VAR* var /**< problem variable */
3326  )
3327 {
3329 }
3330 
3331 /** is it possible, to round variable down and stay feasible?
3332  *
3333  * @note This method will always check w.r.t variable locks of type model
3334  */
3336  SCIP_VAR* var /**< problem variable */
3337  )
3338 {
3339  return (SCIPvarGetNLocksDownType(var, SCIP_LOCKTYPE_MODEL) == 0);
3340 }
3341 
3342 /** is it possible, to round variable up and stay feasible?
3343  *
3344  * @note This method will always check w.r.t. variable locks of type model
3345  */
3347  SCIP_VAR* var /**< problem variable */
3348  )
3349 {
3350  return (SCIPvarGetNLocksUpType(var, SCIP_LOCKTYPE_MODEL) == 0);
3351 }
3352 
3353 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3354  * a new transformed variable for this variable is created
3355  */
3357  SCIP_VAR* origvar, /**< original problem variable */
3358  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3359  SCIP_SET* set, /**< global SCIP settings */
3360  SCIP_STAT* stat, /**< problem statistics */
3361  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3362  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3363  )
3364 {
3365  char name[SCIP_MAXSTRLEN];
3366 
3367  assert(origvar != NULL);
3368  assert(origvar->scip == set->scip);
3369  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3370  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3371  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3372  assert(origvar->vlbs == NULL);
3373  assert(origvar->vubs == NULL);
3374  assert(transvar != NULL);
3375 
3376  /* check if variable is already transformed */
3377  if( origvar->data.original.transvar != NULL )
3378  {
3379  *transvar = origvar->data.original.transvar;
3380  SCIPvarCapture(*transvar);
3381  }
3382  else
3383  {
3384  int i;
3385 
3386  /* create transformed variable */
3387  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3388  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3389  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3390  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3391  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3392 
3393  /* copy the branch factor and priority */
3394  (*transvar)->branchfactor = origvar->branchfactor;
3395  (*transvar)->branchpriority = origvar->branchpriority;
3396  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3397 
3398  /* duplicate hole lists */
3399  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3400  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3401 
3402  /* link original and transformed variable */
3403  origvar->data.original.transvar = *transvar;
3404  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3405 
3406  /* copy rounding locks */
3407  for( i = 0; i < NLOCKTYPES; i++ )
3408  {
3409  (*transvar)->nlocksdown[i] = origvar->nlocksdown[i];
3410  (*transvar)->nlocksup[i] = origvar->nlocksup[i];
3411  assert((*transvar)->nlocksdown[i] >= 0);
3412  assert((*transvar)->nlocksup[i] >= 0);
3413  }
3414 
3415  /* copy doNotMultiaggr status */
3416  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3417 
3418  /* copy lazy bounds */
3419  (*transvar)->lazylb = origvar->lazylb;
3420  (*transvar)->lazyub = origvar->lazyub;
3421 
3422  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3423  * when original variable was created
3424  */
3425  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3426 
3427  /* transform user data */
3428  if( origvar->vartrans != NULL )
3429  {
3430  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3431  }
3432  else
3433  (*transvar)->vardata = origvar->vardata;
3434  }
3435 
3436  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3437 
3438  return SCIP_OKAY;
3439 }
3440 
3441 /** gets corresponding transformed variable of an original or negated original variable */
3443  SCIP_VAR* origvar, /**< original problem variable */
3444  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3445  SCIP_SET* set, /**< global SCIP settings */
3446  SCIP_STAT* stat, /**< problem statistics */
3447  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3448  )
3449 {
3450  assert(origvar != NULL);
3452  assert(origvar->scip == set->scip);
3453 
3454  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3455  {
3456  assert(origvar->negatedvar != NULL);
3458 
3459  if( origvar->negatedvar->data.original.transvar == NULL )
3460  *transvar = NULL;
3461  else
3462  {
3463  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3464  }
3465  }
3466  else
3467  *transvar = origvar->data.original.transvar;
3468 
3469  return SCIP_OKAY;
3470 }
3471 
3472 /** converts loose transformed variable into column variable, creates LP column */
3474  SCIP_VAR* var, /**< problem variable */
3475  BMS_BLKMEM* blkmem, /**< block memory */
3476  SCIP_SET* set, /**< global SCIP settings */
3477  SCIP_STAT* stat, /**< problem statistics */
3478  SCIP_PROB* prob, /**< problem data */
3479  SCIP_LP* lp /**< current LP data */
3480  )
3481 {
3482  assert(var != NULL);
3483  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3484  assert(var->scip == set->scip);
3485 
3486  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3487 
3488  /* switch variable status */
3489  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3490 
3491  /* create column of variable */
3492  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3493 
3494  if( var->probindex != -1 )
3495  {
3496  /* inform problem about the variable's status change */
3497  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3498 
3499  /* inform LP, that problem variable is now a column variable and no longer loose */
3500  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3501  }
3502 
3503  return SCIP_OKAY;
3504 }
3505 
3506 /** converts column transformed variable back into loose variable, frees LP column */
3508  SCIP_VAR* var, /**< problem variable */
3509  BMS_BLKMEM* blkmem, /**< block memory */
3510  SCIP_SET* set, /**< global SCIP settings */
3511  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3512  SCIP_PROB* prob, /**< problem data */
3513  SCIP_LP* lp /**< current LP data */
3514  )
3515 {
3516  assert(var != NULL);
3517  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3518  assert(var->scip == set->scip);
3519  assert(var->data.col != NULL);
3520  assert(var->data.col->lppos == -1);
3521  assert(var->data.col->lpipos == -1);
3522 
3523  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3524 
3525  /* free column of variable */
3526  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3527 
3528  /* switch variable status */
3529  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3530 
3531  if( var->probindex != -1 )
3532  {
3533  /* inform problem about the variable's status change */
3534  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3535 
3536  /* inform LP, that problem variable is now a loose variable and no longer a column */
3537  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3538  }
3539 
3540  return SCIP_OKAY;
3541 }
3542 
3543 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3544  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3545  * are not informed about a fixing of an active variable they are pointing to
3546  */
3547 static
3549  SCIP_VAR* var, /**< problem variable to change */
3550  BMS_BLKMEM* blkmem, /**< block memory */
3551  SCIP_SET* set, /**< global SCIP settings */
3552  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3553  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3554  * multi-aggregation(2)
3555  */
3556  )
3557 {
3558  SCIP_EVENT* event;
3559  SCIP_VARSTATUS varstatus;
3560  int i;
3561 
3562  assert(var != NULL);
3563  assert(var->scip == set->scip);
3564  assert(0 <= fixeventtype && fixeventtype <= 2);
3565 
3566  /* issue VARFIXED event on variable */
3567  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3568  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3569 
3570 #ifndef NDEBUG
3571  for( i = var->nparentvars -1; i >= 0; --i )
3572  {
3574  }
3575 #endif
3576 
3577  switch( fixeventtype )
3578  {
3579  case 0:
3580  /* process all parents of a fixed variable */
3581  for( i = var->nparentvars - 1; i >= 0; --i )
3582  {
3583  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3584 
3585  assert(varstatus != SCIP_VARSTATUS_FIXED);
3586 
3587  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3588  * one
3589  */
3590  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3591  {
3592  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3593  }
3594  }
3595  break;
3596  case 1:
3597  /* process all parents of a aggregated variable */
3598  for( i = var->nparentvars - 1; i >= 0; --i )
3599  {
3600  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3601 
3602  assert(varstatus != SCIP_VARSTATUS_FIXED);
3603 
3604  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3605  * issued(, except the original one)
3606  *
3607  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3608  * yet issued
3609  */
3610  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3611  continue;
3612 
3613  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3614  {
3615  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3616  }
3617  }
3618  break;
3619  case 2:
3620  /* process all parents of a aggregated variable */
3621  for( i = var->nparentvars - 1; i >= 0; --i )
3622  {
3623  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3624 
3625  assert(varstatus != SCIP_VARSTATUS_FIXED);
3626 
3627  /* issue event on all parent variables except the original one */
3628  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3629  {
3630  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3631  }
3632  }
3633  break;
3634  default:
3635  SCIPerrorMessage("unknown variable fixation event origin\n");
3636  return SCIP_INVALIDDATA;
3637  }
3638 
3639  return SCIP_OKAY;
3640 }
3641 
3642 /** converts variable into fixed variable */
3644  SCIP_VAR* var, /**< problem variable */
3645  BMS_BLKMEM* blkmem, /**< block memory */
3646  SCIP_SET* set, /**< global SCIP settings */
3647  SCIP_STAT* stat, /**< problem statistics */
3648  SCIP_PROB* transprob, /**< tranformed problem data */
3649  SCIP_PROB* origprob, /**< original problem data */
3650  SCIP_PRIMAL* primal, /**< primal data */
3651  SCIP_TREE* tree, /**< branch and bound tree */
3652  SCIP_REOPT* reopt, /**< reoptimization data structure */
3653  SCIP_LP* lp, /**< current LP data */
3654  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3655  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
3656  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3657  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3658  SCIP_Real fixedval, /**< value to fix variable at */
3659  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3660  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3661  )
3662 {
3663  SCIP_Real obj;
3664  SCIP_Real childfixedval;
3665 
3666  assert(var != NULL);
3667  assert(var->scip == set->scip);
3668  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3669  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3670  assert(infeasible != NULL);
3671  assert(fixed != NULL);
3672 
3673  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3674 
3675  *infeasible = FALSE;
3676  *fixed = FALSE;
3677 
3679  {
3680  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3681  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3682  return SCIP_OKAY;
3683  }
3684  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3685  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3686  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3687  {
3688  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3689  *infeasible = TRUE;
3690  return SCIP_OKAY;
3691  }
3692 
3693  switch( SCIPvarGetStatus(var) )
3694  {
3696  if( var->data.original.transvar == NULL )
3697  {
3698  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3699  return SCIP_INVALIDDATA;
3700  }
3701  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3702  lp, branchcand, eventfilter, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3703  break;
3704 
3705  case SCIP_VARSTATUS_LOOSE:
3706  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3707 
3708  /* set the fixed variable's objective value to 0.0 */
3709  obj = var->obj;
3710  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3711 
3712  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3713  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3714  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3715  * objective of this variable is set to zero
3716  */
3717  SCIPlpDecNLoosevars(lp);
3718 
3719  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3720  holelistFree(&var->glbdom.holelist, blkmem);
3721  holelistFree(&var->locdom.holelist, blkmem);
3722  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3723  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3724 
3725  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3726  var->glbdom.lb = fixedval;
3727  var->glbdom.ub = fixedval;
3728  var->locdom.lb = fixedval;
3729  var->locdom.ub = fixedval;
3730 
3731  /* delete implications and variable bounds information */
3732  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3733  assert(var->vlbs == NULL);
3734  assert(var->vubs == NULL);
3735  assert(var->implics == NULL);
3736  assert(var->cliquelist == NULL);
3737 
3738  /* clear the history of the variable */
3739  SCIPhistoryReset(var->history);
3741 
3742  /* convert variable into fixed variable */
3743  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3744 
3745  /* inform problem about the variable's status change */
3746  if( var->probindex != -1 )
3747  {
3748  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3749  }
3750 
3751  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3752  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
3753 
3754  /* issue VARFIXED event */
3755  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3756 
3757  *fixed = TRUE;
3758  break;
3759 
3760  case SCIP_VARSTATUS_COLUMN:
3761  SCIPerrorMessage("cannot fix a column variable\n");
3762  return SCIP_INVALIDDATA;
3763 
3764  case SCIP_VARSTATUS_FIXED:
3765  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3766  SCIPABORT(); /* case is already handled in earlier if condition */
3767  return SCIP_INVALIDDATA; /*lint !e527*/
3768 
3770  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3771  assert(SCIPsetIsZero(set, var->obj));
3772  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3773  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3774  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3775  else
3776  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3777  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3778  branchcand, eventfilter, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3779  break;
3780 
3782  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3783  SCIPABORT();
3784  return SCIP_INVALIDDATA; /*lint !e527*/
3785 
3787  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3788  assert(SCIPsetIsZero(set, var->obj));
3789  assert(var->negatedvar != NULL);
3791  assert(var->negatedvar->negatedvar == var);
3792  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3793  branchcand, eventfilter, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3794  break;
3795 
3796  default:
3797  SCIPerrorMessage("unknown variable status\n");
3798  return SCIP_INVALIDDATA;
3799  }
3800 
3801  return SCIP_OKAY;
3802 }
3803 
3804 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3805  *
3806  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3807  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3808  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3809  *
3810  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3811  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3812  */
3814  SCIP_SET* set, /**< global SCIP settings */
3815  SCIP_VAR** vars, /**< variable array to get active variables */
3816  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3817  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3818  int varssize, /**< available slots in vars and scalars array */
3819  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3820  int* requiredsize, /**< pointer to store the required array size for the active variables */
3821  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3822  )
3823 {
3824  SCIP_VAR** activevars;
3825  SCIP_Real* activescalars;
3826  int nactivevars;
3827  SCIP_Real activeconstant;
3828  SCIP_Bool activeconstantinf;
3829  int activevarssize;
3830 
3831  SCIP_VAR* var;
3832  SCIP_Real scalar;
3833  int v;
3834  int k;
3835 
3836  SCIP_VAR** tmpvars;
3837  SCIP_VAR** multvars;
3838  SCIP_Real* tmpscalars;
3839  SCIP_Real* multscalars;
3840  int tmpvarssize;
3841  int ntmpvars;
3842  int nmultvars;
3843 
3844  SCIP_VAR* multvar;
3845  SCIP_Real multscalar;
3846  SCIP_Real multconstant;
3847  int pos;
3848 
3849  int noldtmpvars;
3850 
3851  SCIP_VAR** tmpvars2;
3852  SCIP_Real* tmpscalars2;
3853  int tmpvarssize2;
3854  int ntmpvars2;
3855 
3856  SCIP_Bool sortagain = FALSE;
3857 
3858  assert(set != NULL);
3859  assert(nvars != NULL);
3860  assert(scalars != NULL || *nvars == 0);
3861  assert(constant != NULL);
3862  assert(requiredsize != NULL);
3863  assert(*nvars <= varssize);
3864 
3865  *requiredsize = 0;
3866 
3867  if( *nvars == 0 )
3868  return SCIP_OKAY;
3869 
3870  assert(vars != NULL);
3871 
3872  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3873  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3874  {
3875  *requiredsize = 1;
3876 
3877  return SCIP_OKAY;
3878  }
3879 
3880  nactivevars = 0;
3881  activeconstant = 0.0;
3882  activeconstantinf = FALSE;
3883  activevarssize = (*nvars) * 2;
3884  ntmpvars = *nvars;
3885  tmpvarssize = *nvars;
3886 
3887  tmpvarssize2 = 1;
3888 
3889  /* allocate temporary memory */
3890  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3891  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3892  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3893  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3894  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3895  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3896 
3897  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3898  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3899  */
3900  for( v = ntmpvars - 1; v >= 0; --v )
3901  {
3902  var = tmpvars[v];
3903  scalar = tmpscalars[v];
3904 
3905  assert(var != NULL);
3906  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3907  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3908  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3909  */
3910  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3911  assert(var != NULL);
3912 
3913  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3914  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3915 
3916  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3917 
3918  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3919  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3922 
3923  tmpvars[v] = var;
3924  tmpscalars[v] = scalar;
3925  }
3926  noldtmpvars = ntmpvars;
3927 
3928  /* sort all variables to combine equal variables easily */
3929  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
3930  ntmpvars = 0;
3931  for( v = 1; v < noldtmpvars; ++v )
3932  {
3933  /* combine same variables */
3934  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
3935  {
3936  tmpscalars[ntmpvars] += tmpscalars[v];
3937  }
3938  else
3939  {
3940  ++ntmpvars;
3941  if( v > ntmpvars )
3942  {
3943  tmpscalars[ntmpvars] = tmpscalars[v];
3944  tmpvars[ntmpvars] = tmpvars[v];
3945  }
3946  }
3947  }
3948  ++ntmpvars;
3949 
3950 #ifdef SCIP_MORE_DEBUG
3951  for( v = 1; v < ntmpvars; ++v )
3952  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
3953 #endif
3954 
3955  /* collect for each variable the representation in active variables */
3956  while( ntmpvars >= 1 )
3957  {
3958  --ntmpvars;
3959  ntmpvars2 = 0;
3960  var = tmpvars[ntmpvars];
3961  scalar = tmpscalars[ntmpvars];
3962 
3963  assert(var != NULL);
3964 
3965  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3966  if( scalar == 0.0 )
3967  continue;
3968 
3969  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3970  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3973 
3974  switch( SCIPvarGetStatus(var) )
3975  {
3976  case SCIP_VARSTATUS_LOOSE:
3977  case SCIP_VARSTATUS_COLUMN:
3978  /* x = a*y + c */
3979  if( nactivevars >= activevarssize )
3980  {
3981  activevarssize *= 2;
3982  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3983  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3984  assert(nactivevars < activevarssize);
3985  }
3986  activevars[nactivevars] = var;
3987  activescalars[nactivevars] = scalar;
3988  nactivevars++;
3989  break;
3990 
3992  /* x = a_1*y_1 + ... + a_n*y_n + c */
3993  nmultvars = var->data.multaggr.nvars;
3994  multvars = var->data.multaggr.vars;
3995  multscalars = var->data.multaggr.scalars;
3996  sortagain = TRUE;
3997 
3998  if( nmultvars + ntmpvars > tmpvarssize )
3999  {
4000  while( nmultvars + ntmpvars > tmpvarssize )
4001  tmpvarssize *= 2;
4002  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
4003  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
4004  assert(nmultvars + ntmpvars <= tmpvarssize);
4005  }
4006 
4007  if( nmultvars > tmpvarssize2 )
4008  {
4009  while( nmultvars > tmpvarssize2 )
4010  tmpvarssize2 *= 2;
4011  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
4012  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
4013  assert(nmultvars <= tmpvarssize2);
4014  }
4015 
4016  --nmultvars;
4017 
4018  for( ; nmultvars >= 0; --nmultvars )
4019  {
4020  multvar = multvars[nmultvars];
4021  multscalar = multscalars[nmultvars];
4022  multconstant = 0;
4023 
4024  assert(multvar != NULL);
4025  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
4026  assert(multvar != NULL);
4027 
4028  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
4029  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
4032 
4033  if( !activeconstantinf )
4034  {
4035  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4036 
4037  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4038  {
4039  assert(scalar != 0.0);
4040  if( scalar * multconstant > 0.0 )
4041  {
4042  activeconstant = SCIPsetInfinity(set);
4043  activeconstantinf = TRUE;
4044  }
4045  else
4046  {
4047  activeconstant = -SCIPsetInfinity(set);
4048  activeconstantinf = TRUE;
4049  }
4050  }
4051  else
4052  activeconstant += scalar * multconstant;
4053  }
4054 #ifndef NDEBUG
4055  else
4056  {
4057  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4058  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4059  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4060  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4061  }
4062 #endif
4063 
4064  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
4065  {
4066  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
4067  tmpscalars[pos] += scalar * multscalar;
4068  }
4069  else
4070  {
4071  tmpvars2[ntmpvars2] = multvar;
4072  tmpscalars2[ntmpvars2] = scalar * multscalar;
4073  ++(ntmpvars2);
4074  assert(ntmpvars2 <= tmpvarssize2);
4075  }
4076  }
4077 
4078  if( ntmpvars2 > 0 )
4079  {
4080  /* sort all variables to combine equal variables easily */
4081  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4082  pos = 0;
4083  for( v = 1; v < ntmpvars2; ++v )
4084  {
4085  /* combine same variables */
4086  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4087  {
4088  tmpscalars2[pos] += tmpscalars2[v];
4089  }
4090  else
4091  {
4092  ++pos;
4093  if( v > pos )
4094  {
4095  tmpscalars2[pos] = tmpscalars2[v];
4096  tmpvars2[pos] = tmpvars2[v];
4097  }
4098  }
4099  }
4100  ntmpvars2 = pos + 1;
4101 #ifdef SCIP_MORE_DEBUG
4102  for( v = 1; v < ntmpvars2; ++v )
4103  {
4104  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4105  }
4106  for( v = 1; v < ntmpvars; ++v )
4107  {
4108  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4109  }
4110 #endif
4111  v = ntmpvars - 1;
4112  k = ntmpvars2 - 1;
4113  pos = ntmpvars + ntmpvars2 - 1;
4114  ntmpvars += ntmpvars2;
4115 
4116  while( v >= 0 && k >= 0 )
4117  {
4118  assert(pos >= 0);
4119  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4120  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4121  {
4122  tmpvars[pos] = tmpvars[v];
4123  tmpscalars[pos] = tmpscalars[v];
4124  --v;
4125  }
4126  else
4127  {
4128  tmpvars[pos] = tmpvars2[k];
4129  tmpscalars[pos] = tmpscalars2[k];
4130  --k;
4131  }
4132  --pos;
4133  assert(pos >= 0);
4134  }
4135  while( v >= 0 )
4136  {
4137  assert(pos >= 0);
4138  tmpvars[pos] = tmpvars[v];
4139  tmpscalars[pos] = tmpscalars[v];
4140  --v;
4141  --pos;
4142  }
4143  while( k >= 0 )
4144  {
4145  assert(pos >= 0);
4146  tmpvars[pos] = tmpvars2[k];
4147  tmpscalars[pos] = tmpscalars2[k];
4148  --k;
4149  --pos;
4150  }
4151  }
4152 #ifdef SCIP_MORE_DEBUG
4153  for( v = 1; v < ntmpvars; ++v )
4154  {
4155  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4156  }
4157 #endif
4158 
4159  if( !activeconstantinf )
4160  {
4161  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4162 
4163  multconstant = SCIPvarGetMultaggrConstant(var);
4164 
4165  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4166  {
4167  assert(scalar != 0.0);
4168  if( scalar * multconstant > 0.0 )
4169  {
4170  activeconstant = SCIPsetInfinity(set);
4171  activeconstantinf = TRUE;
4172  }
4173  else
4174  {
4175  activeconstant = -SCIPsetInfinity(set);
4176  activeconstantinf = TRUE;
4177  }
4178  }
4179  else
4180  activeconstant += scalar * multconstant;
4181  }
4182 #ifndef NDEBUG
4183  else
4184  {
4185  multconstant = SCIPvarGetMultaggrConstant(var);
4186  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4187  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4188  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4189  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4190  }
4191 #endif
4192  break;
4193 
4194  case SCIP_VARSTATUS_FIXED:
4198  default:
4199  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4200  * fixed variables and is handled already
4201  */
4202  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4203  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4204  }
4205  }
4206 
4207  if( mergemultiples )
4208  {
4209  if( sortagain )
4210  {
4211  /* sort variable and scalar array by variable index */
4212  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4213 
4214  /* eliminate duplicates and count required size */
4215  v = nactivevars - 1;
4216  while( v > 0 )
4217  {
4218  /* combine both variable since they are the same */
4219  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4220  {
4221  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4222  {
4223  activescalars[v - 1] += activescalars[v];
4224  --nactivevars;
4225  activevars[v] = activevars[nactivevars];
4226  activescalars[v] = activescalars[nactivevars];
4227  }
4228  else
4229  {
4230  --nactivevars;
4231  activevars[v] = activevars[nactivevars];
4232  activescalars[v] = activescalars[nactivevars];
4233  --nactivevars;
4234  --v;
4235  activevars[v] = activevars[nactivevars];
4236  activescalars[v] = activescalars[nactivevars];
4237  }
4238  }
4239  --v;
4240  }
4241  }
4242  /* the variables were added in reverse order, we revert the order now;
4243  * this should not be necessary, but not doing this changes the behavior sometimes
4244  */
4245  else
4246  {
4247  SCIP_VAR* tmpvar;
4248  SCIP_Real tmpscalar;
4249 
4250  for( v = 0; v < nactivevars / 2; ++v )
4251  {
4252  tmpvar = activevars[v];
4253  tmpscalar = activescalars[v];
4254  activevars[v] = activevars[nactivevars - 1 - v];
4255  activescalars[v] = activescalars[nactivevars - 1 - v];
4256  activevars[nactivevars - 1 - v] = tmpvar;
4257  activescalars[nactivevars - 1 - v] = tmpscalar;
4258  }
4259  }
4260  }
4261  *requiredsize = nactivevars;
4262 
4263  if( varssize >= *requiredsize )
4264  {
4265  assert(vars != NULL);
4266 
4267  *nvars = *requiredsize;
4268 
4269  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4270  {
4271  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4272  if( activeconstantinf )
4273  (*constant) = activeconstant;
4274  else
4275  (*constant) += activeconstant;
4276  }
4277 #ifndef NDEBUG
4278  else
4279  {
4280  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4281  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4282  }
4283 #endif
4284 
4285  /* copy active variable and scalar array to the given arrays */
4286  for( v = 0; v < *nvars; ++v )
4287  {
4288  vars[v] = activevars[v];
4289  scalars[v] = activescalars[v]; /*lint !e613*/
4290  }
4291  }
4292 
4293  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4294  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4295 
4296  SCIPsetFreeBufferArray(set, &tmpscalars);
4297  SCIPsetFreeBufferArray(set, &tmpvars);
4298  SCIPsetFreeBufferArray(set, &activescalars);
4299  SCIPsetFreeBufferArray(set, &activevars);
4300  SCIPsetFreeBufferArray(set, &tmpscalars2);
4301  SCIPsetFreeBufferArray(set, &tmpvars2);
4302 
4303  return SCIP_OKAY;
4304 }
4305 
4306 
4307 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4309  SCIP_VAR* var, /**< problem variable */
4310  BMS_BLKMEM* blkmem, /**< block memory */
4311  SCIP_SET* set, /**< global SCIP settings */
4312  SCIP_EVENTQUEUE* eventqueue /**< event queue */
4313  )
4314 {
4315  int nlocksup[NLOCKTYPES];
4316  int nlocksdown[NLOCKTYPES];
4317  SCIP_Real multconstant;
4318  int multvarssize;
4319  int nmultvars;
4320  int multrequiredsize;
4321  int i;
4322 
4323  assert( var != NULL );
4324  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4325  assert(var->scip == set->scip);
4326 
4327  /* in order to update the locks on the active representation of the multi-aggregated variable, we remove all locks
4328  * on the current representation now and re-add the locks once the variable graph has been flattened, which
4329  * may lead to duplicate occurences of the same variable being merged
4330  *
4331  * Here is an example. Assume we have the multi-aggregation z = x + y.
4332  * z occures with positive coefficient in a <= constraint c1, so it has an uplock from there.
4333  * When the multi-aggregation is performed, all locks are added to the active representation,
4334  * so x and y both get an uplock from c1. However, z was not yet replaced by x + y in c1.
4335  * Next, a negation y = 1 - x is identified. Again, locks are moved, so that the uplock of y originating
4336  * from c1 is added to x as a downlock. Thus, x has both an up- and downlock from c1.
4337  * The multi-aggregation changes to z = x + 1 - x, which corresponds to the locks.
4338  * However, before z is replaced by that sum, SCIPvarFlattenAggregationGraph() is called
4339  * which changes z = x + y = x + 1 - x = 1, since it merges multiple occurences of the same variable.
4340  * The up- and downlock of x, however, is not removed when replacing z in c1 by its active representation,
4341  * because it is just 1 now. Therefore, we need to update locks when flattening the aggregation graph.
4342  * For this, the multi-aggregated variable knows its locks in addition to adding them to the active
4343  * representation, which corresponds to the locks from constraints where the variable was not replaced yet.
4344  * By removing the locks here, based on the old representation and adding them again after flattening,
4345  * we ensure that the locks are correct afterwards if coefficients were merged.
4346  */
4347  for( i = 0; i < NLOCKTYPES; ++i )
4348  {
4349  nlocksup[i] = var->nlocksup[i];
4350  nlocksdown[i] = var->nlocksdown[i];
4351 
4352  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, -nlocksdown[i], -nlocksup[i]) );
4353  }
4354 
4355  multconstant = var->data.multaggr.constant;
4356  nmultvars = var->data.multaggr.nvars;
4357  multvarssize = var->data.multaggr.varssize;
4358 
4359  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4360 
4361  if( multrequiredsize > multvarssize )
4362  {
4363  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4364  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4365  multvarssize = multrequiredsize;
4366  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4367  assert( multrequiredsize <= multvarssize );
4368  }
4369  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4370  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4371  * may loose performance hereby, since aggregated variables are easier to handle.
4372  *
4373  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4374  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4375  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4376  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4377  *
4378  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4379  *
4380  * The same issue appears in the SCIPvarGetProbvar...() methods.
4381  */
4382 
4383  var->data.multaggr.constant = multconstant;
4384  var->data.multaggr.nvars = nmultvars;
4385  var->data.multaggr.varssize = multvarssize;
4386 
4387  for( i = 0; i < NLOCKTYPES; ++i )
4388  {
4389  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4390  }
4391 
4392  return SCIP_OKAY;
4393 }
4394 
4395 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4396  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4397  * the history merge is reasonable
4398  *
4399  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4400  * this corrupts the variable pseudo costs
4401  * @note Apply with care; no internal checks are performed if the two variables should be merged
4402  */
4404  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4405  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4406  SCIP_STAT* stat /**< problem statistics */
4407  )
4408 {
4409  /* merge only the history of the current run into the target history */
4410  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4411 
4412  /* apply the changes also to the global history */
4413  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4414 }
4415 
4416 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4417  * history over several iterations
4418  */
4419 void SCIPvarSetHistory(
4420  SCIP_VAR* var, /**< variable */
4421  SCIP_HISTORY* history, /**< the history which is to set */
4422  SCIP_STAT* stat /**< problem statistics */
4423  )
4424 {
4425  /* merge only the history of the current run into the target history */
4426  SCIPhistoryUnite(var->history, history, FALSE);
4427 
4428  /* apply the changes also to the global history */
4429  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4430 }
4431 
4432 /** tightens the bounds of both variables in aggregation x = a*y + c */
4433 static
4435  SCIP_VAR* var, /**< problem variable */
4436  BMS_BLKMEM* blkmem, /**< block memory */
4437  SCIP_SET* set, /**< global SCIP settings */
4438  SCIP_STAT* stat, /**< problem statistics */
4439  SCIP_PROB* transprob, /**< tranformed problem data */
4440  SCIP_PROB* origprob, /**< original problem data */
4441  SCIP_PRIMAL* primal, /**< primal data */
4442  SCIP_TREE* tree, /**< branch and bound tree */
4443  SCIP_REOPT* reopt, /**< reoptimization data structure */
4444  SCIP_LP* lp, /**< current LP data */
4445  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4446  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4447  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4448  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4449  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4450  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4451  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4452  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4453  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4454  )
4455 {
4456  SCIP_Real varlb;
4457  SCIP_Real varub;
4458  SCIP_Real aggvarlb;
4459  SCIP_Real aggvarub;
4460  SCIP_Bool aggvarbdschanged;
4461 
4462  assert(var != NULL);
4463  assert(var->scip == set->scip);
4464  assert(aggvar != NULL);
4465  assert(!SCIPsetIsZero(set, scalar));
4466  assert(infeasible != NULL);
4467  assert(fixed != NULL);
4468 
4469  *infeasible = FALSE;
4470  *fixed = FALSE;
4471 
4472  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4473  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4474  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4475 
4476  /* loop as long additional changes may be found */
4477  do
4478  {
4479  aggvarbdschanged = FALSE;
4480 
4481  /* update the bounds of the aggregated variable x in x = a*y + c */
4482  if( scalar > 0.0 )
4483  {
4484  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4485  varlb = -SCIPsetInfinity(set);
4486  else
4487  varlb = aggvar->glbdom.lb * scalar + constant;
4488  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4489  varub = SCIPsetInfinity(set);
4490  else
4491  varub = aggvar->glbdom.ub * scalar + constant;
4492  }
4493  else
4494  {
4495  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4496  varub = SCIPsetInfinity(set);
4497  else
4498  varub = aggvar->glbdom.lb * scalar + constant;
4499  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4500  varlb = -SCIPsetInfinity(set);
4501  else
4502  varlb = aggvar->glbdom.ub * scalar + constant;
4503  }
4504  varlb = MAX(varlb, var->glbdom.lb);
4505  varub = MIN(varub, var->glbdom.ub);
4506  SCIPvarAdjustLb(var, set, &varlb);
4507  SCIPvarAdjustUb(var, set, &varub);
4508 
4509  /* check the new bounds */
4510  if( SCIPsetIsGT(set, varlb, varub) )
4511  {
4512  /* the aggregation is infeasible */
4513  *infeasible = TRUE;
4514  return SCIP_OKAY;
4515  }
4516  else if( SCIPsetIsEQ(set, varlb, varub) )
4517  {
4518  /* the aggregated variable is fixed -> fix both variables */
4519  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4520  eventfilter, eventqueue, cliquetable, varlb, infeasible, fixed) );
4521  if( !(*infeasible) )
4522  {
4523  SCIP_Bool aggfixed;
4524 
4525  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4526  eventfilter, eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4527  assert(*fixed == aggfixed);
4528  }
4529  return SCIP_OKAY;
4530  }
4531  else
4532  {
4533  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4534  {
4535  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4536  }
4537  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4538  {
4539  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4540  }
4541 
4542  /* update the hole list of the aggregation variable */
4543  /**@todo update hole list of aggregation variable */
4544  }
4545 
4546  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4547  if( scalar > 0.0 )
4548  {
4549  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4550  aggvarlb = -SCIPsetInfinity(set);
4551  else
4552  aggvarlb = (var->glbdom.lb - constant) / scalar;
4553  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4554  aggvarub = SCIPsetInfinity(set);
4555  else
4556  aggvarub = (var->glbdom.ub - constant) / scalar;
4557  }
4558  else
4559  {
4560  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4561  aggvarub = SCIPsetInfinity(set);
4562  else
4563  aggvarub = (var->glbdom.lb - constant) / scalar;
4564  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4565  aggvarlb = -SCIPsetInfinity(set);
4566  else
4567  aggvarlb = (var->glbdom.ub - constant) / scalar;
4568  }
4569  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4570  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4571  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4572  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4573 
4574  /* check the new bounds */
4575  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4576  {
4577  /* the aggregation is infeasible */
4578  *infeasible = TRUE;
4579  return SCIP_OKAY;
4580  }
4581  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4582  {
4583  /* the aggregation variable is fixed -> fix both variables */
4584  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4585  eventfilter, eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4586  if( !(*infeasible) )
4587  {
4588  SCIP_Bool varfixed;
4589 
4590  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4591  eventfilter, eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4592  assert(*fixed == varfixed);
4593  }
4594  return SCIP_OKAY;
4595  }
4596  else
4597  {
4598  SCIP_Real oldbd;
4599  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4600  {
4601  oldbd = aggvar->glbdom.lb;
4602  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4603  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4604  }
4605  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4606  {
4607  oldbd = aggvar->glbdom.ub;
4608  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4609  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4610  }
4611 
4612  /* update the hole list of the aggregation variable */
4613  /**@todo update hole list of aggregation variable */
4614  }
4615  }
4616  while( aggvarbdschanged );
4617 
4618  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4619  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4620 
4621  return SCIP_OKAY;
4622 }
4623 
4624 /** converts loose variable into aggregated variable */
4626  SCIP_VAR* var, /**< loose problem variable */
4627  BMS_BLKMEM* blkmem, /**< block memory */
4628  SCIP_SET* set, /**< global SCIP settings */
4629  SCIP_STAT* stat, /**< problem statistics */
4630  SCIP_PROB* transprob, /**< tranformed problem data */
4631  SCIP_PROB* origprob, /**< original problem data */
4632  SCIP_PRIMAL* primal, /**< primal data */
4633  SCIP_TREE* tree, /**< branch and bound tree */
4634  SCIP_REOPT* reopt, /**< reoptimization data structure */
4635  SCIP_LP* lp, /**< current LP data */
4636  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4637  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4638  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4639  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4640  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4641  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4642  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4643  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4644  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4645  )
4646 {
4647  SCIP_VAR** vars;
4648  SCIP_Real* coefs;
4649  SCIP_Real* constants;
4650  SCIP_Real obj;
4651  SCIP_Real branchfactor;
4652  SCIP_Bool fixed;
4653  int branchpriority;
4654  int nlocksdown[NLOCKTYPES];
4655  int nlocksup[NLOCKTYPES];
4656  int nvbds;
4657  int i;
4658  int j;
4659 
4660  assert(var != NULL);
4661  assert(aggvar != NULL);
4662  assert(var->scip == set->scip);
4663  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4664  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4665  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4666  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4667  assert(infeasible != NULL);
4668  assert(aggregated != NULL);
4669 
4670  /* check aggregation on debugging solution */
4671  SCIP_CALL( SCIPdebugCheckAggregation(set, var, &aggvar, &scalar, constant, 1) ); /*lint !e506 !e774*/
4672 
4673  *infeasible = FALSE;
4674  *aggregated = FALSE;
4675 
4676  /* get active problem variable of aggregation variable */
4677  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4678 
4679  /* aggregation is a fixing, if the scalar is zero */
4680  if( SCIPsetIsZero(set, scalar) )
4681  {
4682  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventfilter,
4683  eventqueue, cliquetable, constant, infeasible, aggregated) );
4684  return SCIP_OKAY;
4685  }
4686 
4687  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4688  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4689  return SCIP_OKAY;
4690 
4691  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4692  * should be changed in the future
4693  */
4694  if( SCIPvarGetHolelistGlobal(var) != NULL )
4695  return SCIP_OKAY;
4696 
4697  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4698  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4699  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4700 
4701  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4702  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4703 
4704  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4705  if( var == aggvar )
4706  {
4707  if( SCIPsetIsEQ(set, scalar, 1.0) )
4708  *infeasible = !SCIPsetIsZero(set, constant);
4709  else
4710  {
4711  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4712  eventfilter, eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4713  }
4714  return SCIP_OKAY;
4715  }
4716 
4717  /* tighten the bounds of aggregated and aggregation variable */
4718  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4719  branchcand, eventfilter, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4720  if( *infeasible || fixed )
4721  {
4722  *aggregated = fixed;
4723  return SCIP_OKAY;
4724  }
4725 
4726  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4727  * aggregated variable
4728  */
4729  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4730  assert(var->cliquelist == NULL);
4731 
4732  /* set the aggregated variable's objective value to 0.0 */
4733  obj = var->obj;
4734  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4735 
4736  /* unlock all locks */
4737  for( i = 0; i < NLOCKTYPES; i++ )
4738  {
4739  nlocksdown[i] = var->nlocksdown[i];
4740  nlocksup[i] = var->nlocksup[i];
4741 
4742  var->nlocksdown[i] = 0;
4743  var->nlocksup[i] = 0;
4744  }
4745 
4746  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4747  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4748  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4749  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4750  {
4751  /* link both variables as negation pair */
4752  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4753  var->data.negate.constant = 1.0;
4754  var->negatedvar = aggvar;
4755  aggvar->negatedvar = var;
4756 
4757  /* copy doNotMultiaggr status */
4758  aggvar->donotmultaggr |= var->donotmultaggr;
4759 
4760  /* mark both variables to be non-deletable */
4762  SCIPvarMarkNotDeletable(aggvar);
4763  }
4764  else
4765  {
4766  /* convert variable into aggregated variable */
4767  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4768  var->data.aggregate.var = aggvar;
4769  var->data.aggregate.scalar = scalar;
4770  var->data.aggregate.constant = constant;
4771 
4772  /* copy doNotMultiaggr status */
4773  aggvar->donotmultaggr |= var->donotmultaggr;
4774 
4775  /* mark both variables to be non-deletable */
4777  SCIPvarMarkNotDeletable(aggvar);
4778  }
4779 
4780  /* make aggregated variable a parent of the aggregation variable */
4781  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4782 
4783  /* relock the variable, thus increasing the locks of the aggregation variable */
4784  for( i = 0; i < NLOCKTYPES; i++ )
4785  {
4786  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
4787  }
4788 
4789  /* move the variable bounds to the aggregation variable:
4790  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4791  * - free the variable bounds data structures
4792  */
4793  if( var->vlbs != NULL )
4794  {
4795  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4796  vars = SCIPvboundsGetVars(var->vlbs);
4797  coefs = SCIPvboundsGetCoefs(var->vlbs);
4798  constants = SCIPvboundsGetConstants(var->vlbs);
4799  for( i = 0; i < nvbds && !(*infeasible); ++i )
4800  {
4801  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4802  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4803  }
4804  }
4805  if( var->vubs != NULL )
4806  {
4807  nvbds = SCIPvboundsGetNVbds(var->vubs);
4808  vars = SCIPvboundsGetVars(var->vubs);
4809  coefs = SCIPvboundsGetCoefs(var->vubs);
4810  constants = SCIPvboundsGetConstants(var->vubs);
4811  for( i = 0; i < nvbds && !(*infeasible); ++i )
4812  {
4813  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4814  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4815  }
4816  }
4817  SCIPvboundsFree(&var->vlbs, blkmem);
4818  SCIPvboundsFree(&var->vubs, blkmem);
4819 
4820  /* move the implications to the aggregation variable:
4821  * - add all implications again to the variable, thus adding it to the aggregation variable
4822  * - free the implications data structures
4823  */
4824  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4825  {
4826  assert(SCIPvarIsBinary(var));
4827  for( i = 0; i < 2; ++i )
4828  {
4829  SCIP_VAR** implvars;
4830  SCIP_BOUNDTYPE* impltypes;
4831  SCIP_Real* implbounds;
4832  int nimpls;
4833 
4834  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4835  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4836  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4837  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4838 
4839  for( j = 0; j < nimpls && !(*infeasible); ++j )
4840  {
4841  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4842  * implication to the aggregated variable?
4843  */
4844  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4845  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4846  NULL) );
4847  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4848  }
4849  }
4850  }
4851  SCIPimplicsFree(&var->implics, blkmem);
4852 
4853  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4854  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4855  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4856  SCIPhistoryReset(var->history);
4858 
4859  /* update flags of aggregation variable */
4860  aggvar->removable &= var->removable;
4861 
4862  /* update branching factors and priorities of both variables to be the maximum of both variables */
4863  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4864  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4865  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4866  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4867  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4868  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4869 
4870  /* update branching direction of both variables to agree to a single direction */
4871  if( scalar >= 0.0 )
4872  {
4874  {
4876  }
4877  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4878  {
4880  }
4881  else if( var->branchdirection != aggvar->branchdirection )
4882  {
4884  }
4885  }
4886  else
4887  {
4889  {
4891  }
4892  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4893  {
4895  }
4896  else if( var->branchdirection != aggvar->branchdirection )
4897  {
4899  }
4900  }
4901 
4902  if( var->probindex != -1 )
4903  {
4904  /* inform problem about the variable's status change */
4905  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4906  }
4907 
4908  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4909  * variable and the problem's objective offset
4910  */
4911  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
4912 
4913  /* issue VARFIXED event */
4914  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4915 
4916  *aggregated = TRUE;
4917 
4918  return SCIP_OKAY;
4919 }
4920 
4921 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4922  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4923  *
4924  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4925  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4926  */
4927 static
4929  SCIP_SET* set, /**< global SCIP settings */
4930  BMS_BLKMEM* blkmem, /**< block memory */
4931  SCIP_STAT* stat, /**< problem statistics */
4932  SCIP_PROB* transprob, /**< tranformed problem data */
4933  SCIP_PROB* origprob, /**< original problem data */
4934  SCIP_PRIMAL* primal, /**< primal data */
4935  SCIP_TREE* tree, /**< branch and bound tree */
4936  SCIP_REOPT* reopt, /**< reoptimization data structure */
4937  SCIP_LP* lp, /**< current LP data */
4938  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4939  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4940  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4941  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4942  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4943  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4944  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4945  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4946  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4947  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4948  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4949  )
4950 {
4951  SCIP_VAR* aggvar;
4952  char aggvarname[SCIP_MAXSTRLEN];
4953  SCIP_Longint scalarxn = 0;
4954  SCIP_Longint scalarxd = 0;
4955  SCIP_Longint scalaryn = 0;
4956  SCIP_Longint scalaryd = 0;
4957  SCIP_Longint a;
4958  SCIP_Longint b;
4959  SCIP_Longint c;
4960  SCIP_Longint scm;
4961  SCIP_Longint gcd;
4962  SCIP_Longint currentclass;
4963  SCIP_Longint classstep;
4964  SCIP_Longint xsol;
4965  SCIP_Longint ysol;
4966  SCIP_Bool success;
4967  SCIP_VARTYPE vartype;
4968 
4969 #define MAXDNOM 1000000LL
4970 
4971  assert(set != NULL);
4972  assert(blkmem != NULL);
4973  assert(stat != NULL);
4974  assert(transprob != NULL);
4975  assert(origprob != NULL);
4976  assert(tree != NULL);
4977  assert(lp != NULL);
4978  assert(cliquetable != NULL);
4979  assert(branchcand != NULL);
4980  assert(eventqueue != NULL);
4981  assert(varx != NULL);
4982  assert(vary != NULL);
4983  assert(varx != vary);
4984  assert(infeasible != NULL);
4985  assert(aggregated != NULL);
4986  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4987  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4989  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4991  assert(!SCIPsetIsZero(set, scalarx));
4992  assert(!SCIPsetIsZero(set, scalary));
4993 
4994  *infeasible = FALSE;
4995  *aggregated = FALSE;
4996 
4997  /* get rational representation of coefficients */
4998  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4999  if( success )
5000  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
5001  if( !success )
5002  return SCIP_OKAY;
5003  assert(scalarxd >= 1);
5004  assert(scalaryd >= 1);
5005 
5006  /* multiply equality with smallest common denominator */
5007  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
5008  a = (scm/scalarxd)*scalarxn;
5009  b = (scm/scalaryd)*scalaryn;
5010  rhs *= scm;
5011 
5012  /* divide equality by the greatest common divisor of a and b */
5013  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
5014  a /= gcd;
5015  b /= gcd;
5016  rhs /= gcd;
5017  assert(a != 0);
5018  assert(b != 0);
5019 
5020  /* check, if right hand side is integral */
5021  if( !SCIPsetIsFeasIntegral(set, rhs) )
5022  {
5023  *infeasible = TRUE;
5024  return SCIP_OKAY;
5025  }
5026  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
5027 
5028  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5029  return SCIP_OKAY;
5030 
5031  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5032  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5033  {
5034  /* aggregate x = - b/a*y + c/a */
5035  /*lint --e{653}*/
5036  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5037  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5038  assert(*aggregated);
5039  return SCIP_OKAY;
5040  }
5041  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5042  {
5043  /* aggregate y = - a/b*x + c/b */
5044  /*lint --e{653}*/
5045  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5046  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5047  assert(*aggregated);
5048  return SCIP_OKAY;
5049  }
5050 
5051  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5052  * common divisor. Let (x',y') be a solution of the equality
5053  * a*x + b*y == c -> a*x == c - b*y
5054  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5055  */
5056 
5057  /* find initial solution (x',y'):
5058  * - find y' such that c - b*y' is a multiple of a
5059  * - start in equivalence class c%a
5060  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5061  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5062  * - 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
5063  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5064  *
5065  * Algorithm works for a > 0 only.
5066  */
5067  if( a < 0 )
5068  {
5069  a = -a;
5070  b = -b;
5071  c = -c;
5072  }
5073  assert(0 <= a);
5074 
5075  /* search upwards from ysol = 0 */
5076  ysol = 0;
5077  currentclass = c % a;
5078  if( currentclass < 0 )
5079  currentclass += a;
5080  assert(0 <= currentclass && currentclass < a);
5081 
5082  classstep = (-b) % a;
5083 
5084  if( classstep < 0 )
5085  classstep += a;
5086  assert(0 <= classstep && classstep < a);
5087 
5088  while( currentclass != 0 )
5089  {
5090  assert(0 <= currentclass && currentclass < a);
5091  currentclass += classstep;
5092  if( currentclass >= a )
5093  currentclass -= a;
5094  ysol++;
5095  }
5096  assert(ysol < a);
5097  assert(((c - b*ysol) % a) == 0);
5098 
5099  xsol = (c - b*ysol)/a;
5100 
5101  /* determine variable type for new artificial variable:
5102  *
5103  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5104  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5105  * integral type
5106  */
5109 
5110  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5111  * - create new integer variable z with infinite bounds
5112  * - aggregate variable x = -b*z + x'
5113  * - aggregate variable y = a*z + y'
5114  * - the bounds of z are calculated automatically during aggregation
5115  */
5116  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5117  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5118  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5120  NULL, NULL, NULL, NULL, NULL) );
5121 
5122  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5123 
5124  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5125  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5126  assert(*aggregated || *infeasible);
5127 
5128  if( !(*infeasible) )
5129  {
5130  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5131  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5132  assert(*aggregated || *infeasible);
5133  }
5134 
5135  /* release z */
5136  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5137 
5138  return SCIP_OKAY;
5139 } /*lint !e438*/
5140 
5141 /** performs second step of SCIPaggregateVars():
5142  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5143  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5144  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5145  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5146  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5147  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5148  *
5149  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5150  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5151  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5152  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5153  */
5155  SCIP_SET* set, /**< global SCIP settings */
5156  BMS_BLKMEM* blkmem, /**< block memory */
5157  SCIP_STAT* stat, /**< problem statistics */
5158  SCIP_PROB* transprob, /**< tranformed problem data */
5159  SCIP_PROB* origprob, /**< original problem data */
5160  SCIP_PRIMAL* primal, /**< primal data */
5161  SCIP_TREE* tree, /**< branch and bound tree */
5162  SCIP_REOPT* reopt, /**< reoptimization data structure */
5163  SCIP_LP* lp, /**< current LP data */
5164  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5165  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5166  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5167  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5168  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5169  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5170  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5171  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5172  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5173  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5174  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5175  )
5176 {
5177  SCIP_Bool easyaggr;
5178  SCIP_Real maxscalar;
5179  SCIP_Real absquot;
5180 
5181  assert(set != NULL);
5182  assert(blkmem != NULL);
5183  assert(stat != NULL);
5184  assert(transprob != NULL);
5185  assert(origprob != NULL);
5186  assert(tree != NULL);
5187  assert(lp != NULL);
5188  assert(cliquetable != NULL);
5189  assert(branchcand != NULL);
5190  assert(eventqueue != NULL);
5191  assert(varx != NULL);
5192  assert(vary != NULL);
5193  assert(varx != vary);
5194  assert(infeasible != NULL);
5195  assert(aggregated != NULL);
5196  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5197  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5198  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5199  assert(!SCIPsetIsZero(set, scalarx));
5200  assert(!SCIPsetIsZero(set, scalary));
5201 
5202  *infeasible = FALSE;
5203  *aggregated = FALSE;
5204 
5205  absquot = REALABS(scalarx / scalary);
5206  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5207  maxscalar = MAX(maxscalar, 1.0);
5208 
5209  if( absquot > maxscalar || absquot < 1 / maxscalar )
5210  return SCIP_OKAY;
5211 
5212  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5213  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5214  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5215  {
5216  SCIP_VAR* var;
5217  SCIP_Real scalar;
5218 
5219  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5220  var = vary;
5221  vary = varx;
5222  varx = var;
5223  scalar = scalary;
5224  scalary = scalarx;
5225  scalarx = scalar;
5226  }
5227 
5228  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5229  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5230  return SCIP_OKAY;
5231 
5232  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5233 
5234  /* figure out, which variable should be aggregated */
5235  easyaggr = FALSE;
5236 
5237  /* check if it is an easy aggregation that means:
5238  *
5239  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5240  */
5241  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5242  {
5244  {
5245  easyaggr = TRUE;
5246  }
5247  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5248  {
5249  easyaggr = TRUE;
5250  }
5251  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5252  {
5253  /* we have an easy aggregation if we flip the variables x and y */
5254  SCIP_VAR* var;
5255  SCIP_Real scalar;
5256 
5257  /* switch the variables, such that varx is the aggregated variable */
5258  var = vary;
5259  vary = varx;
5260  varx = var;
5261  scalar = scalary;
5262  scalary = scalarx;
5263  scalarx = scalar;
5264  easyaggr = TRUE;
5265  }
5266  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5267  {
5268  /* the aggregation is still easy if both variables are continuous */
5269  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5270  easyaggr = TRUE;
5271  }
5272  }
5273 
5274  /* did we find an "easy" aggregation? */
5275  if( easyaggr )
5276  {
5277  SCIP_Real scalar;
5278  SCIP_Real constant;
5279 
5280  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5281 
5282  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5283  scalar = -scalary/scalarx;
5284  constant = rhs/scalarx;
5285 
5286  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5287  return SCIP_OKAY;
5288 
5289  /* check aggregation for integer feasibility */
5292  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5293  {
5294  *infeasible = TRUE;
5295  return SCIP_OKAY;
5296  }
5297 
5298  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5299  * since then we would loose the corresponding divisibility property
5300  */
5301  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5302 
5303  /* aggregate the variable */
5304  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5305  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5306  assert(*aggregated || *infeasible);
5307  }
5310  {
5311  /* the variables are both integral: we have to try to find an integer aggregation */
5312  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5313  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5314  }
5315 
5316  return SCIP_OKAY;
5317 }
5318 
5319 /** converts variable into multi-aggregated variable */
5321  SCIP_VAR* var, /**< problem variable */
5322  BMS_BLKMEM* blkmem, /**< block memory */
5323  SCIP_SET* set, /**< global SCIP settings */
5324  SCIP_STAT* stat, /**< problem statistics */
5325  SCIP_PROB* transprob, /**< tranformed problem data */
5326  SCIP_PROB* origprob, /**< original problem data */
5327  SCIP_PRIMAL* primal, /**< primal data */
5328  SCIP_TREE* tree, /**< branch and bound tree */
5329  SCIP_REOPT* reopt, /**< reoptimization data structure */
5330  SCIP_LP* lp, /**< current LP data */
5331  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5332  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5333  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5334  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5335  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5336  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5337  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5338  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5339  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5340  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5341  )
5342 {
5343  SCIP_VAR** tmpvars;
5344  SCIP_Real* tmpscalars;
5345  SCIP_Real obj;
5346  SCIP_Real branchfactor;
5347  int branchpriority;
5348  SCIP_BRANCHDIR branchdirection;
5349  int nlocksdown[NLOCKTYPES];
5350  int nlocksup[NLOCKTYPES];
5351  int v;
5352  SCIP_Real tmpconstant;
5353  SCIP_Real tmpscalar;
5354  int ntmpvars;
5355  int tmpvarssize;
5356  int tmprequiredsize;
5357  int i;
5358 
5359  assert(var != NULL);
5360  assert(var->scip == set->scip);
5361  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5362  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5363  assert(naggvars == 0 || aggvars != NULL);
5364  assert(naggvars == 0 || scalars != NULL);
5365  assert(infeasible != NULL);
5366  assert(aggregated != NULL);
5367 
5368  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5369 
5370  /* check multi-aggregation on debugging solution */
5371  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5372 
5373  *infeasible = FALSE;
5374  *aggregated = FALSE;
5375 
5376  switch( SCIPvarGetStatus(var) )
5377  {
5379  if( var->data.original.transvar == NULL )
5380  {
5381  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5382  return SCIP_INVALIDDATA;
5383  }
5384  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5385  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5386  break;
5387 
5388  case SCIP_VARSTATUS_LOOSE:
5389  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5390 
5391  /* check if we would create a self-reference */
5392  ntmpvars = naggvars;
5393  tmpvarssize = naggvars;
5394  tmpconstant = constant;
5395  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5396  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5397 
5398  /* get all active variables for multi-aggregation */
5399  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5400  if( tmprequiredsize > tmpvarssize )
5401  {
5402  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5403  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5404  tmpvarssize = tmprequiredsize;
5405  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5406  assert( tmprequiredsize <= tmpvarssize );
5407  }
5408 
5409  tmpscalar = 0.0;
5410 
5411  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5412  * possible multi-aggregated variable
5413  */
5414  for( v = ntmpvars - 1; v >= 0; --v )
5415  {
5416  assert(tmpvars[v] != NULL);
5417  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5418 
5419  if( tmpvars[v]->index == var->index )
5420  {
5421  tmpscalar += tmpscalars[v];
5422  tmpvars[v] = tmpvars[ntmpvars - 1];
5423  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5424  --ntmpvars;
5425  }
5426  }
5427 
5428  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5429  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5430  {
5431  if( ntmpvars == 0 )
5432  {
5433  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5434  {
5435  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5436  goto TERMINATE;
5437  }
5438  else /* 0 = c and c != 0 */
5439  {
5440  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5441  *infeasible = TRUE;
5442  goto TERMINATE;
5443  }
5444  }
5445  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5446  {
5447  assert(tmpscalars[0] != 0.0);
5448  assert(tmpvars[0] != NULL);
5449 
5450  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5451  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5452  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5453  goto TERMINATE;
5454  }
5455  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 */
5456  {
5457  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5458 
5459  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5460  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5461 
5462  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5463  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5464  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5465 
5466  goto TERMINATE;
5467  }
5468  else
5469  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5470  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5471  */
5472  goto TERMINATE;
5473  }
5474  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5475  else if( !SCIPsetIsZero(set, tmpscalar) )
5476  {
5477  tmpscalar = 1 - tmpscalar;
5478  tmpconstant /= tmpscalar;
5479  for( v = ntmpvars - 1; v >= 0; --v )
5480  tmpscalars[v] /= tmpscalar;
5481  }
5482 
5483  /* check, if we are in one of the simple cases */
5484  if( ntmpvars == 0 )
5485  {
5486  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5487  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5488  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5489  goto TERMINATE;
5490  }
5491 
5492  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5493  if( ntmpvars == 1 )
5494  {
5495  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5496  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5497 
5498  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5499  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5500  infeasible, aggregated) );
5501 
5502  goto TERMINATE;
5503  }
5504 
5505  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5506  * empty hole list; this should be changed in the future */
5507  if( SCIPvarGetHolelistGlobal(var) != NULL )
5508  goto TERMINATE;
5509 
5510  /* if the variable is not allowed to be multi-aggregated */
5511  if( SCIPvarDoNotMultaggr(var) )
5512  {
5513  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5514  goto TERMINATE;
5515  }
5516 
5517  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5518  * variable bound variable of another variable), we have to remove it from the other variables implications or
5519  * variable bounds
5520  */
5521  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5522  assert(var->vlbs == NULL);
5523  assert(var->vubs == NULL);
5524  assert(var->implics == NULL);
5525  assert(var->cliquelist == NULL);
5526 
5527  /* set the aggregated variable's objective value to 0.0 */
5528  obj = var->obj;
5529  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5530 
5531  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5532  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5533  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5534  * objective of this variable is set to zero
5535  */
5536  SCIPlpDecNLoosevars(lp);
5537 
5538  /* unlock all rounding locks */
5539  for( i = 0; i < NLOCKTYPES; i++ )
5540  {
5541  nlocksdown[i] = var->nlocksdown[i];
5542  nlocksup[i] = var->nlocksup[i];
5543 
5544  var->nlocksdown[i] = 0;
5545  var->nlocksup[i] = 0;
5546  }
5547 
5548  /* convert variable into multi-aggregated variable */
5549  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5550  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5551  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5552  var->data.multaggr.constant = tmpconstant;
5553  var->data.multaggr.nvars = ntmpvars;
5554  var->data.multaggr.varssize = ntmpvars;
5555 
5556  /* mark variable to be non-deletable */
5558 
5559  /* relock the variable, thus increasing the locks of the aggregation variables */
5560  for( i = 0; i < NLOCKTYPES; i++ )
5561  {
5562  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5563  }
5564 
5565  /* update flags and branching factors and priorities of aggregation variables;
5566  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5567  */
5568  branchfactor = var->branchfactor;
5569  branchpriority = var->branchpriority;
5570  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5571 
5572  for( v = 0; v < ntmpvars; ++v )
5573  {
5574  assert(tmpvars[v] != NULL);
5575  tmpvars[v]->removable &= var->removable;
5576  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5577  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5578 
5579  /* mark variable to be non-deletable */
5580  SCIPvarMarkNotDeletable(tmpvars[v]);
5581  }
5582  for( v = 0; v < ntmpvars; ++v )
5583  {
5584  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5585  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5586  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5587  {
5588  if( tmpscalars[v] >= 0.0 )
5589  {
5590  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5591  }
5592  else
5593  {
5594  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5595  }
5596  }
5597  }
5598  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5599  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5600 
5601  if( var->probindex != -1 )
5602  {
5603  /* inform problem about the variable's status change */
5604  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5605  }
5606 
5607  /* issue VARFIXED event */
5608  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5609 
5610  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5611  * variables and the problem's objective offset
5612  */
5613  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5614 
5615  *aggregated = TRUE;
5616 
5617  TERMINATE:
5618  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5619  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5620 
5621  break;
5622 
5623  case SCIP_VARSTATUS_COLUMN:
5624  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5625  return SCIP_INVALIDDATA;
5626 
5627  case SCIP_VARSTATUS_FIXED:
5628  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5629  return SCIP_INVALIDDATA;
5630 
5632  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5633  return SCIP_INVALIDDATA;
5634 
5636  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5637  return SCIP_INVALIDDATA;
5638 
5640  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5641  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5642  */
5643  assert(SCIPsetIsZero(set, var->obj));
5644  assert(var->negatedvar != NULL);
5646  assert(var->negatedvar->negatedvar == var);
5647 
5648  /* switch the signs of the aggregation scalars */
5649  for( v = 0; v < naggvars; ++v )
5650  scalars[v] *= -1.0;
5651 
5652  /* perform the multi aggregation on the negation variable */
5653  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5654  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5655  var->data.negate.constant - constant, infeasible, aggregated) );
5656 
5657  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5658  for( v = 0; v < naggvars; ++v )
5659  scalars[v] *= -1.0;
5660  break;
5661 
5662  default:
5663  SCIPerrorMessage("unknown variable status\n");
5664  return SCIP_INVALIDDATA;
5665  }
5666 
5667  return SCIP_OKAY;
5668 }
5669 
5670 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5671  * or for original variables the same variable is returned
5672  */
5673 static
5675  SCIP_VAR* var /**< problem variable */
5676  )
5677 {
5678  SCIP_VAR* retvar;
5679 
5680  assert(var != NULL);
5681 
5682  retvar = var;
5683 
5684  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5685 
5686  while( TRUE ) /*lint !e716 */
5687  {
5688  assert(retvar != NULL);
5689 
5690  switch( SCIPvarGetStatus(retvar) )
5691  {
5693  case SCIP_VARSTATUS_LOOSE:
5694  case SCIP_VARSTATUS_COLUMN:
5695  case SCIP_VARSTATUS_FIXED:
5696  return retvar;
5697 
5699  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5700  if ( retvar->data.multaggr.nvars == 1 )
5701  retvar = retvar->data.multaggr.vars[0];
5702  else
5703  return retvar;
5704  break;
5705 
5707  retvar = retvar->data.aggregate.var;
5708  break;
5709 
5711  retvar = retvar->negatedvar;
5712  break;
5713 
5714  default:
5715  SCIPerrorMessage("unknown variable status\n");
5716  SCIPABORT();
5717  return NULL; /*lint !e527*/
5718  }
5719  }
5720 }
5721 
5722 /** returns whether variable is not allowed to be multi-aggregated */
5724  SCIP_VAR* var /**< problem variable */
5725  )
5726 {
5727  SCIP_VAR* retvar;
5728 
5729  assert(var != NULL);
5730 
5731  retvar = varGetActiveVar(var);
5732  assert(retvar != NULL);
5733 
5734  switch( SCIPvarGetStatus(retvar) )
5735  {
5737  case SCIP_VARSTATUS_LOOSE:
5738  case SCIP_VARSTATUS_COLUMN:
5739  case SCIP_VARSTATUS_FIXED:
5740  return retvar->donotmultaggr;
5741 
5743  return FALSE;
5744 
5747  default:
5748  SCIPerrorMessage("wrong variable status\n");
5749  SCIPABORT();
5750  return FALSE; /*lint !e527 */
5751  }
5752 }
5753 
5754 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5755  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5756  * negated variable is created
5757  */
5759  SCIP_VAR* var, /**< problem variable to negate */
5760  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5761  SCIP_SET* set, /**< global SCIP settings */
5762  SCIP_STAT* stat, /**< problem statistics */
5763  SCIP_VAR** negvar /**< pointer to store the negated variable */
5764  )
5765 {
5766  assert(var != NULL);
5767  assert(var->scip == set->scip);
5768  assert(negvar != NULL);
5769 
5770  /* check, if we already created the negated variable */
5771  if( var->negatedvar == NULL )
5772  {
5773  char negvarname[SCIP_MAXSTRLEN];
5774 
5775  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5776 
5777  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5778 
5779  /* negation is only possible for bounded variables */
5780  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5781  {
5782  SCIPerrorMessage("cannot negate unbounded variable\n");
5783  return SCIP_INVALIDDATA;
5784  }
5785 
5786  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5787 
5788  /* create negated variable */
5789  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5790  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5791  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5792  if( SCIPvarIsBinary(var) )
5793  (*negvar)->data.negate.constant = 1.0;
5794  else
5795  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5796 
5797  /* create event filter for transformed variable */
5798  if( SCIPvarIsTransformed(var) )
5799  {
5800  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5801  }
5802 
5803  /* set the bounds corresponding to the negation variable */
5804  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5805  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5806  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5807  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5808  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5809 
5810  /* link the variables together */
5811  var->negatedvar = *negvar;
5812  (*negvar)->negatedvar = var;
5813 
5814  /* mark both variables to be non-deletable */
5816  SCIPvarMarkNotDeletable(*negvar);
5817 
5818  /* copy the branch factor and priority, and use the negative preferred branching direction */
5819  (*negvar)->branchfactor = var->branchfactor;
5820  (*negvar)->branchpriority = var->branchpriority;
5821  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5822 
5823  /* copy doNotMultiaggr status */
5824  (*negvar)->donotmultaggr = var->donotmultaggr;
5825 
5826  /* copy lazy bounds (they have to be flipped) */
5827  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5828  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5829 
5830  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5831  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5832  assert((*negvar)->nuses == 1);
5833  }
5834  assert(var->negatedvar != NULL);
5835 
5836  /* return the negated variable */
5837  *negvar = var->negatedvar;
5838 
5839  /* exactly one variable of the negation pair has to be marked as negated variable */
5841 
5842  return SCIP_OKAY;
5843 }
5844 
5845 /** informs variable that its position in problem's vars array changed */
5846 static
5847 void varSetProbindex(
5848  SCIP_VAR* var, /**< problem variable */
5849  int probindex /**< new problem index of variable (-1 for removal) */
5850  )
5851 {
5852  assert(var != NULL);
5853  assert(probindex >= 0 || var->vlbs == NULL);
5854  assert(probindex >= 0 || var->vubs == NULL);
5855  assert(probindex >= 0 || var->implics == NULL);
5856 
5857  var->probindex = probindex;
5859  {
5860  assert(var->data.col != NULL);
5861  var->data.col->var_probindex = probindex;
5862  }
5863 }
5864 
5865 /** informs variable that its position in problem's vars array changed */
5866 void SCIPvarSetProbindex(
5867  SCIP_VAR* var, /**< problem variable */
5868  int probindex /**< new problem index of variable */
5869  )
5870 {
5871  assert(var != NULL);
5872  assert(probindex >= 0);
5873 
5874  varSetProbindex(var, probindex);
5875 }
5876 
5877 /** gives the variable a new name
5878  *
5879  * @note the old pointer is overwritten, which might result in a memory leakage
5880  */
5882  SCIP_VAR* var, /**< problem variable */
5883  const char* name /**< new name of variable */
5884  )
5885 {
5886  assert(var != NULL);
5887  assert(name != NULL);
5888 
5889  var->name = (char*)name;
5890 }
5891 
5892 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5893  * implication graph;
5894  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5895  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5896  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5897  * than removing the variables one by one, each time updating all lists of the other variables.
5898  */
5900  SCIP_VAR* var, /**< problem variable */
5901  BMS_BLKMEM* blkmem, /**< block memory buffer */
5902  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5903  SCIP_SET* set, /**< global SCIP settings */
5904  SCIP_Bool final /**< is this the final removal of all problem variables? */
5905  )
5906 {
5907  assert(SCIPvarGetProbindex(var) >= 0);
5908  assert(var->scip == set->scip);
5909 
5910  /* if the variable is active in the transformed problem, remove it from the implication graph */
5911  if( SCIPvarIsTransformed(var)
5913  {
5914  if( final )
5915  {
5916  /* just destroy the data structures */
5917  SCIPvboundsFree(&var->vlbs, blkmem);
5918  SCIPvboundsFree(&var->vubs, blkmem);
5919  SCIPimplicsFree(&var->implics, blkmem);
5920  }
5921  else
5922  {
5923  /* unlink the variable from all other variables' lists and free the data structures */
5924  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5925  }
5926  }
5927 
5928  /* mark the variable to be no longer a member of the problem */
5929  varSetProbindex(var, -1);
5930 
5931  return SCIP_OKAY;
5932 }
5933 
5934 /** marks the variable to be deleted from the problem */
5935 void SCIPvarMarkDeleted(
5936  SCIP_VAR* var /**< problem variable */
5937  )
5938 {
5939  assert(var != NULL);
5940  assert(var->probindex != -1);
5941 
5942  var->deleted = TRUE;
5943 }
5944 
5945 /** marks the variable to not to be multi-aggregated */
5947  SCIP_VAR* var /**< problem variable */
5948  )
5949 {
5950  SCIP_VAR* retvar;
5951 
5952  assert(var != NULL);
5953 
5954  retvar = varGetActiveVar(var);
5955  assert(retvar != NULL);
5956 
5957  switch( SCIPvarGetStatus(retvar) )
5958  {
5960  case SCIP_VARSTATUS_LOOSE:
5961  case SCIP_VARSTATUS_COLUMN:
5962  case SCIP_VARSTATUS_FIXED:
5963  retvar->donotmultaggr = TRUE;
5964  break;
5965 
5967  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5968  return SCIP_INVALIDDATA;
5969 
5972  default:
5973  SCIPerrorMessage("wrong variable status\n");
5974  return SCIP_INVALIDDATA;
5975  }
5976 
5977  return SCIP_OKAY;
5978 }
5979 
5980 /** changes type of variable; cannot be called, if var belongs to a problem */
5982  SCIP_VAR* var, /**< problem variable to change */
5983  BMS_BLKMEM* blkmem, /**< block memory */
5984  SCIP_SET* set, /**< global SCIP settings */
5985  SCIP_PRIMAL* primal, /**< primal data */
5986  SCIP_LP* lp, /**< current LP data */
5987  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5988  SCIP_VARTYPE vartype /**< new type of variable */
5989  )
5990 {
5991  SCIP_EVENT* event;
5992  SCIP_VARTYPE oldtype;
5993 
5994  assert(var != NULL);
5995 
5996  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5997 
5998  if( var->probindex >= 0 )
5999  {
6000  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6001  return SCIP_INVALIDDATA;
6002  }
6003 
6004  oldtype = (SCIP_VARTYPE)var->vartype;
6005  var->vartype = vartype; /*lint !e641*/
6006 
6008  {
6009  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6010  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6011  }
6012 
6013  if( var->negatedvar != NULL )
6014  {
6015  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6016  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6017 
6018 
6019  var->negatedvar->vartype = vartype; /*lint !e641*/
6020 
6022  {
6023  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6024  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6025  }
6026  }
6027 
6028  return SCIP_OKAY;
6029 }
6030 
6031 /** appends OBJCHANGED event to the event queue */
6032 static
6034  SCIP_VAR* var, /**< problem variable to change */
6035  BMS_BLKMEM* blkmem, /**< block memory */
6036  SCIP_SET* set, /**< global SCIP settings */
6037  SCIP_PRIMAL* primal, /**< primal data */
6038  SCIP_LP* lp, /**< current LP data */
6039  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6040  SCIP_Real oldobj, /**< old objective value for variable */
6041  SCIP_Real newobj /**< new objective value for variable */
6042  )
6043 {
6044  SCIP_EVENT* event;
6045 
6046  assert(var != NULL);
6047  assert(var->scip == set->scip);
6048  assert(var->eventfilter != NULL);
6050  assert(SCIPvarIsTransformed(var));
6051 
6052  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6053  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6054  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6055  * that make comparison with values close to epsilon inaccurate.
6056  */
6057  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6058  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6059  );
6060 
6061  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6062  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6063 
6064  return SCIP_OKAY;
6065 }
6066 
6067 /** changes objective value of variable */
6069  SCIP_VAR* var, /**< variable to change */
6070  BMS_BLKMEM* blkmem, /**< block memory */
6071  SCIP_SET* set, /**< global SCIP settings */
6072  SCIP_PROB* prob, /**< problem data */
6073  SCIP_PRIMAL* primal, /**< primal data */
6074  SCIP_LP* lp, /**< current LP data */
6075  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6076  SCIP_Real newobj /**< new objective value for variable */
6077  )
6078 {
6079  SCIP_Real oldobj;
6080 
6081  assert(var != NULL);
6082  assert(set != NULL);
6083  assert(var->scip == set->scip);
6084 
6085  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6086 
6087  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6088  {
6089  switch( SCIPvarGetStatus(var) )
6090  {
6092  if( var->data.original.transvar != NULL )
6093  {
6094  assert(SCIPprobIsTransformed(prob));
6095 
6096  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6097  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6098  }
6099  else
6100  assert(set->stage == SCIP_STAGE_PROBLEM);
6101 
6102  var->obj = newobj;
6103  var->unchangedobj = newobj;
6104 
6105  break;
6106 
6107  case SCIP_VARSTATUS_LOOSE:
6108  case SCIP_VARSTATUS_COLUMN:
6109  oldobj = var->obj;
6110  var->obj = newobj;
6111 
6112  /* update unchanged objective value of variable */
6113  if( !lp->divingobjchg )
6114  var->unchangedobj = newobj;
6115 
6116  /* update the number of variables with non-zero objective coefficient;
6117  * we only want to do the update, if the variable is added to the problem;
6118  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6119  */
6120  if( SCIPvarIsActive(var) )
6121  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6122 
6123  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6124  break;
6125 
6126  case SCIP_VARSTATUS_FIXED:
6130  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6131  return SCIP_INVALIDDATA;
6132 
6133  default:
6134  SCIPerrorMessage("unknown variable status\n");
6135  return SCIP_INVALIDDATA;
6136  }
6137  }
6138 
6139  return SCIP_OKAY;
6140 }
6141 
6142 /** adds value to objective value of variable */
6144  SCIP_VAR* var, /**< variable to change */
6145  BMS_BLKMEM* blkmem, /**< block memory */
6146  SCIP_SET* set, /**< global SCIP settings */
6147  SCIP_STAT* stat, /**< problem statistics */
6148  SCIP_PROB* transprob, /**< transformed problem data */
6149  SCIP_PROB* origprob, /**< original problem data */
6150  SCIP_PRIMAL* primal, /**< primal data */
6151  SCIP_TREE* tree, /**< branch and bound tree */
6152  SCIP_REOPT* reopt, /**< reoptimization data structure */
6153  SCIP_LP* lp, /**< current LP data */
6154  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6155  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6156  SCIP_Real addobj /**< additional objective value for variable */
6157  )
6158 {
6159  assert(var != NULL);
6160  assert(set != NULL);
6161  assert(var->scip == set->scip);
6162  assert(set->stage < SCIP_STAGE_INITSOLVE);
6163 
6164  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6165 
6166  if( !SCIPsetIsZero(set, addobj) )
6167  {
6168  SCIP_Real oldobj;
6169  int i;
6170 
6171  switch( SCIPvarGetStatus(var) )
6172  {
6174  if( var->data.original.transvar != NULL )
6175  {
6176  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6177  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6178  }
6179  else
6180  assert(set->stage == SCIP_STAGE_PROBLEM);
6181 
6182  var->obj += addobj;
6183  var->unchangedobj += addobj;
6184  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6185 
6186  break;
6187 
6188  case SCIP_VARSTATUS_LOOSE:
6189  case SCIP_VARSTATUS_COLUMN:
6190  oldobj = var->obj;
6191  var->obj += addobj;
6192 
6193  /* update unchanged objective value of variable */
6194  if( !lp->divingobjchg )
6195  {
6196  var->unchangedobj += addobj;
6197  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6198  }
6199 
6200  /* update the number of variables with non-zero objective coefficient;
6201  * we only want to do the update, if the variable is added to the problem;
6202  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6203  */
6204  if( SCIPvarIsActive(var) )
6205  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6206 
6207  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6208  break;
6209 
6210  case SCIP_VARSTATUS_FIXED:
6211  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6212  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6213  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6214  break;
6215 
6217  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6218  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6219  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6220  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6221  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6222  break;
6223 
6225  assert(!var->donotmultaggr);
6226  /* 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 */
6227  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6228  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6229  for( i = 0; i < var->data.multaggr.nvars; ++i )
6230  {
6231  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6232  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6233  }
6234  break;
6235 
6237  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6238  assert(var->negatedvar != NULL);
6240  assert(var->negatedvar->negatedvar == var);
6241  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6242  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6243  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6244  eventfilter, eventqueue, -addobj) );
6245  break;
6246 
6247  default:
6248  SCIPerrorMessage("unknown variable status\n");
6249  return SCIP_INVALIDDATA;
6250  }
6251  }
6252 
6253  return SCIP_OKAY;
6254 }
6255 
6256 /** changes objective value of variable in current dive */
6258  SCIP_VAR* var, /**< problem variable to change */
6259  SCIP_SET* set, /**< global SCIP settings */
6260  SCIP_LP* lp, /**< current LP data */
6261  SCIP_Real newobj /**< new objective value for variable */
6262  )
6263 {
6264  assert(var != NULL);
6265  assert(set != NULL);
6266  assert(var->scip == set->scip);
6267  assert(lp != NULL);
6268 
6269  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6270 
6271  if( SCIPsetIsZero(set, newobj) )
6272  newobj = 0.0;
6273 
6274  /* change objective value of attached variables */
6275  switch( SCIPvarGetStatus(var) )
6276  {
6278  assert(var->data.original.transvar != NULL);
6279  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6280  break;
6281 
6282  case SCIP_VARSTATUS_COLUMN:
6283  assert(var->data.col != NULL);
6284  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6285  break;
6286 
6287  case SCIP_VARSTATUS_LOOSE:
6288  case SCIP_VARSTATUS_FIXED:
6289  /* nothing to do here: only the constant shift in objective function would change */
6290  break;
6291 
6292  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6293  assert(var->data.aggregate.var != NULL);
6294  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6295  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6296  /* the constant can be ignored, because it would only affect the objective shift */
6297  break;
6298 
6300  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6301  return SCIP_INVALIDDATA;
6302 
6303  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6304  assert(var->negatedvar != NULL);
6306  assert(var->negatedvar->negatedvar == var);
6307  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6308  /* the offset can be ignored, because it would only affect the objective shift */
6309  break;
6310 
6311  default:
6312  SCIPerrorMessage("unknown variable status\n");
6313  return SCIP_INVALIDDATA;
6314  }
6315 
6316  return SCIP_OKAY;
6317 }
6318 
6319 /** adjust lower bound to integral value, if variable is integral */
6320 void SCIPvarAdjustLb(
6321  SCIP_VAR* var, /**< problem variable */
6322  SCIP_SET* set, /**< global SCIP settings */
6323  SCIP_Real* lb /**< pointer to lower bound to adjust */
6324  )
6325 {
6326  assert(var != NULL);
6327  assert(set != NULL);
6328  assert(var->scip == set->scip);
6329  assert(lb != NULL);
6330 
6331  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6332 
6333  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6334 }
6335 
6336 /** adjust upper bound to integral value, if variable is integral */
6337 void SCIPvarAdjustUb(
6338  SCIP_VAR* var, /**< problem variable */
6339  SCIP_SET* set, /**< global SCIP settings */
6340  SCIP_Real* ub /**< pointer to upper bound to adjust */
6341  )
6342 {
6343  assert(var != NULL);
6344  assert(set != NULL);
6345  assert(var->scip == set->scip);
6346  assert(ub != NULL);
6347 
6348  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6349 
6350  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6351 }
6352 
6353 /** adjust lower or upper bound to integral value, if variable is integral */
6354 void SCIPvarAdjustBd(
6355  SCIP_VAR* var, /**< problem variable */
6356  SCIP_SET* set, /**< global SCIP settings */
6357  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6358  SCIP_Real* bd /**< pointer to bound to adjust */
6359  )
6360 {
6361  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6362 
6363  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6364  SCIPvarAdjustLb(var, set, bd);
6365  else
6366  SCIPvarAdjustUb(var, set, bd);
6367 }
6368 
6369 /** changes lower bound of original variable in original problem */
6371  SCIP_VAR* var, /**< problem variable to change */
6372  SCIP_SET* set, /**< global SCIP settings */
6373  SCIP_Real newbound /**< new bound for variable */
6374  )
6375 {
6376  int i;
6377 
6378  assert(var != NULL);
6379  assert(!SCIPvarIsTransformed(var));
6381  assert(set != NULL);
6382  assert(var->scip == set->scip);
6383  assert(set->stage == SCIP_STAGE_PROBLEM);
6384 
6385  /* check that the bound is feasible */
6386  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6387  /* adjust bound to integral value if variable is of integral type */
6388  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6389 
6390  if( SCIPsetIsZero(set, newbound) )
6391  newbound = 0.0;
6392 
6393  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6395  {
6396  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6397  var->name, var->data.original.origdom.lb, newbound);
6398 
6399  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6400  return SCIP_OKAY;
6401 
6402  /* change the bound */
6403  var->data.original.origdom.lb = newbound;
6404  }
6405  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6406  {
6407  assert( var->negatedvar != NULL );
6408  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6409  }
6410 
6411  /* process parent variables */
6412  for( i = 0; i < var->nparentvars; ++i )
6413  {
6414  SCIP_VAR* parentvar;
6415 
6416  parentvar = var->parentvars[i];
6417  assert(parentvar != NULL);
6418  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6419  assert(parentvar->negatedvar == var);
6420  assert(var->negatedvar == parentvar);
6421 
6422  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6423  }
6424 
6425  return SCIP_OKAY;
6426 }
6427 
6428 /** changes upper bound of original variable in original problem */
6430  SCIP_VAR* var, /**< problem variable to change */
6431  SCIP_SET* set, /**< global SCIP settings */
6432  SCIP_Real newbound /**< new bound for variable */
6433  )
6434 {
6435  int i;
6436 
6437  assert(var != NULL);
6438  assert(!SCIPvarIsTransformed(var));
6440  assert(set != NULL);
6441  assert(var->scip == set->scip);
6442  assert(set->stage == SCIP_STAGE_PROBLEM);
6443 
6444  /* check that the bound is feasible */
6445  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6446  /* adjust bound to integral value if variable is of integral type */
6447  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6448 
6449  if( SCIPsetIsZero(set, newbound) )
6450  newbound = 0.0;
6451 
6452  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6454  {
6455  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6456  var->name, var->data.original.origdom.ub, newbound);
6457 
6458  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6459  return SCIP_OKAY;
6460 
6461  /* change the bound */
6462  var->data.original.origdom.ub = newbound;
6463  }
6464  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6465  {
6466  assert( var->negatedvar != NULL );
6467  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6468  }
6469 
6470  /* process parent variables */
6471  for( i = 0; i < var->nparentvars; ++i )
6472  {
6473  SCIP_VAR* parentvar;
6474 
6475  parentvar = var->parentvars[i];
6476  assert(parentvar != NULL);
6477  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6478  assert(parentvar->negatedvar == var);
6479  assert(var->negatedvar == parentvar);
6480 
6481  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6482  }
6483 
6484  return SCIP_OKAY;
6485 }
6486 
6487 /** appends GLBCHANGED event to the event queue */
6488 static
6490  SCIP_VAR* var, /**< problem variable to change */
6491  BMS_BLKMEM* blkmem, /**< block memory */
6492  SCIP_SET* set, /**< global SCIP settings */
6493  SCIP_LP* lp, /**< current LP data */
6494  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6495  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6496  SCIP_Real oldbound, /**< old lower bound for variable */
6497  SCIP_Real newbound /**< new lower bound for variable */
6498  )
6499 {
6500  assert(var != NULL);
6501  assert(var->eventfilter != NULL);
6502  assert(SCIPvarIsTransformed(var));
6503  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6504  assert(set != NULL);
6505  assert(var->scip == set->scip);
6506 
6507  /* check, if the variable is being tracked for bound changes
6508  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6509  */
6510  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6513  {
6514  SCIP_EVENT* event;
6515 
6516  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6517 
6518  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6519  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6520  }
6521 
6522  return SCIP_OKAY;
6523 }
6524 
6525 /** appends GUBCHANGED event to the event queue */
6526 static
6528  SCIP_VAR* var, /**< problem variable to change */
6529  BMS_BLKMEM* blkmem, /**< block memory */
6530  SCIP_SET* set, /**< global SCIP settings */
6531  SCIP_LP* lp, /**< current LP data */
6532  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6533  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6534  SCIP_Real oldbound, /**< old lower bound for variable */
6535  SCIP_Real newbound /**< new lower bound for variable */
6536  )
6537 {
6538  assert(var != NULL);
6539  assert(var->eventfilter != NULL);
6540  assert(SCIPvarIsTransformed(var));
6541  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6542  assert(set != NULL);
6543  assert(var->scip == set->scip);
6544 
6545  /* check, if the variable is being tracked for bound changes
6546  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6547  */
6548  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6551  {
6552  SCIP_EVENT* event;
6553 
6554  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6555 
6556  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6557  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6558  }
6559 
6560  return SCIP_OKAY;
6561 }
6562 
6563 /** appends GHOLEADDED event to the event queue */
6564 static
6566  SCIP_VAR* var, /**< problem variable to change */
6567  BMS_BLKMEM* blkmem, /**< block memory */
6568  SCIP_SET* set, /**< global SCIP settings */
6569  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6570  SCIP_Real left, /**< left bound of open interval in new hole */
6571  SCIP_Real right /**< right bound of open interval in new hole */
6572  )
6573 {
6574  assert(var != NULL);
6575  assert(var->eventfilter != NULL);
6576  assert(SCIPvarIsTransformed(var));
6577  assert(set != NULL);
6578  assert(var->scip == set->scip);
6579  assert(SCIPsetIsLT(set, left, right));
6580 
6581  /* check, if the variable is being tracked for bound changes */
6582  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6583  {
6584  SCIP_EVENT* event;
6585 
6586  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6587 
6588  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6589  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6590  }
6591 
6592  return SCIP_OKAY;
6593 }
6594 
6595 /** increases root bound change statistics after a global bound change */
6596 static
6597 void varIncRootboundchgs(
6598  SCIP_VAR* var, /**< problem variable to change */
6599  SCIP_SET* set, /**< global SCIP settings */
6600  SCIP_STAT* stat /**< problem statistics */
6601  )
6602 {
6603  assert(var != NULL);
6604  assert(set != NULL);
6605  assert(var->scip == set->scip);
6606  assert(stat != NULL);
6607 
6608  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6609  {
6610  stat->nrootboundchgs++;
6611  stat->nrootboundchgsrun++;
6612  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6613  {
6614  stat->nrootintfixings++;
6615  stat->nrootintfixingsrun++;
6616  }
6617  }
6618 }
6619 
6620 /* forward declaration, because both methods call each other recursively */
6621 
6622 /* performs the current change in upper bound, changes all parents accordingly */
6623 static
6625  SCIP_VAR* var, /**< problem variable to change */
6626  BMS_BLKMEM* blkmem, /**< block memory */
6627  SCIP_SET* set, /**< global SCIP settings */
6628  SCIP_STAT* stat, /**< problem statistics */
6629  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6630  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6631  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6632  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6633  SCIP_Real newbound /**< new bound for variable */
6634  );
6635 
6636 /** performs the current change in lower bound, changes all parents accordingly */
6637 static
6639  SCIP_VAR* var, /**< problem variable to change */
6640  BMS_BLKMEM* blkmem, /**< block memory */
6641  SCIP_SET* set, /**< global SCIP settings */
6642  SCIP_STAT* stat, /**< problem statistics */
6643  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6644  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6645  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6646  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6647  SCIP_Real newbound /**< new bound for variable */
6648  )
6649 {
6650  SCIP_VAR* parentvar;
6651  SCIP_Real oldbound;
6652  int i;
6653 
6654  assert(var != NULL);
6655  /* local domains can violate global bounds but not more than feasibility epsilon */
6656  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6657  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6658  assert(blkmem != NULL);
6659  assert(set != NULL);
6660  assert(var->scip == set->scip);
6661  assert(stat != NULL);
6662 
6663  /* adjust bound to integral value if variable is of integral type */
6664  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6665 
6666  /* check that the bound is feasible */
6667  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6668  {
6669  /* due to numerics we only want to be feasible in feasibility tolerance */
6670  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6671  newbound = var->glbdom.ub;
6672  }
6673  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6674 
6675  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6676 
6677  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6678 
6679  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6680  return SCIP_OKAY;
6681 
6682  /* check bound on debugging solution */
6683  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6684 
6685  /* change the bound */
6686  oldbound = var->glbdom.lb;
6687  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6688  var->glbdom.lb = newbound;
6689  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6690  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6691 
6692  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6693  {
6694  /* merges overlapping holes into single holes, moves bounds respectively */
6695  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6696  }
6697 
6698  /* update the root bound changes counters */
6699  varIncRootboundchgs(var, set, stat);
6700 
6701  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6702  * redundant bound changes to be branching decisions
6703  */
6704  for( i = 0; i < var->nlbchginfos; ++i )
6705  {
6706  assert(var->lbchginfos[i].var == var);
6707 
6708  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6709  {
6710  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6711  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6712  var->lbchginfos[i].oldbound = var->glbdom.lb;
6713  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6714  {
6715  /* this bound change is redundant due to the new global bound */
6716  var->lbchginfos[i].newbound = var->glbdom.lb;
6717  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6718  var->lbchginfos[i].redundant = TRUE;
6719  }
6720  else
6721  break; /* from now on, the remaining local bound changes are not redundant */
6722  }
6723  else
6724  break; /* from now on, the remaining local bound changes are not redundant */
6725  }
6726 
6727  /* remove redundant implications and variable bounds */
6729  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6730  {
6731  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6732  }
6733 
6734  /* issue bound change event */
6735  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6736  if( var->eventfilter != NULL )
6737  {
6738  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6739  }
6740 
6741  /* process parent variables */
6742  for( i = 0; i < var->nparentvars; ++i )
6743  {
6744  parentvar = var->parentvars[i];
6745  assert(parentvar != NULL);
6746 
6747  switch( SCIPvarGetStatus(parentvar) )
6748  {
6750  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6751  break;
6752 
6753  case SCIP_VARSTATUS_COLUMN:
6754  case SCIP_VARSTATUS_LOOSE:
6755  case SCIP_VARSTATUS_FIXED:
6757  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6758  return SCIP_INVALIDDATA;
6759 
6760  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6761  assert(parentvar->data.aggregate.var == var);
6762  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6763  {
6764  SCIP_Real parentnewbound;
6765 
6766  /* a > 0 -> change lower bound of y */
6767  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6768  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6769  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6770 
6771  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6772  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6773  else
6774  parentnewbound = newbound;
6775  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6776  }
6777  else
6778  {
6779  SCIP_Real parentnewbound;
6780 
6781  /* a < 0 -> change upper bound of y */
6782  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6783  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6784  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6785  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6786 
6787  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6788  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6789  else
6790  parentnewbound = -newbound;
6791  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6792  }
6793  break;
6794 
6795  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6796  assert(parentvar->negatedvar != NULL);
6797  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6798  assert(parentvar->negatedvar->negatedvar == parentvar);
6799  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6800  parentvar->data.negate.constant - newbound) );
6801  break;
6802 
6803  default:
6804  SCIPerrorMessage("unknown variable status\n");
6805  return SCIP_INVALIDDATA;
6806  }
6807  }
6808 
6809  return SCIP_OKAY;
6810 }
6811 
6812 /** performs the current change in upper bound, changes all parents accordingly */
6813 static
6815  SCIP_VAR* var, /**< problem variable to change */
6816  BMS_BLKMEM* blkmem, /**< block memory */
6817  SCIP_SET* set, /**< global SCIP settings */
6818  SCIP_STAT* stat, /**< problem statistics */
6819  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6820  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6821  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6822  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6823  SCIP_Real newbound /**< new bound for variable */
6824  )
6825 {
6826  SCIP_VAR* parentvar;
6827  SCIP_Real oldbound;
6828  int i;
6829 
6830  assert(var != NULL);
6831  /* local domains can violate global bounds but not more than feasibility epsilon */
6832  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6833  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6834  assert(blkmem != NULL);
6835  assert(set != NULL);
6836  assert(var->scip == set->scip);
6837  assert(stat != NULL);
6838 
6839  /* adjust bound to integral value if variable is of integral type */
6840  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6841 
6842  /* check that the bound is feasible */
6843  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6844  {
6845  /* due to numerics we only want to be feasible in feasibility tolerance */
6846  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6847  newbound = var->glbdom.lb;
6848  }
6849  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6850 
6851  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6852 
6853  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6854 
6855  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
6856  return SCIP_OKAY;
6857 
6858  /* check bound on debugging solution */
6859  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6860 
6861  /* change the bound */
6862  oldbound = var->glbdom.ub;
6863  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6864  var->glbdom.ub = newbound;
6865  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6866  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6867 
6868  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6869  {
6870  /* merges overlapping holes into single holes, moves bounds respectively */
6871  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6872  }
6873 
6874  /* update the root bound changes counters */
6875  varIncRootboundchgs(var, set, stat);
6876 
6877  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6878  * redundant bound changes to be branching decisions
6879  */
6880  for( i = 0; i < var->nubchginfos; ++i )
6881  {
6882  assert(var->ubchginfos[i].var == var);
6883  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6884  {
6885  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6886  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6887  var->ubchginfos[i].oldbound = var->glbdom.ub;
6888  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6889  {
6890  /* this bound change is redundant due to the new global bound */
6891  var->ubchginfos[i].newbound = var->glbdom.ub;
6892  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6893  var->ubchginfos[i].redundant = TRUE;
6894  }
6895  else
6896  break; /* from now on, the remaining local bound changes are not redundant */
6897  }
6898  else
6899  break; /* from now on, the remaining local bound changes are not redundant */
6900  }
6901 
6902  /* remove redundant implications and variable bounds */
6904  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6905  {
6906  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6907  }
6908 
6909  /* issue bound change event */
6910  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6911  if( var->eventfilter != NULL )
6912  {
6913  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6914  }
6915 
6916  /* process parent variables */
6917  for( i = 0; i < var->nparentvars; ++i )
6918  {
6919  parentvar = var->parentvars[i];
6920  assert(parentvar != NULL);
6921 
6922  switch( SCIPvarGetStatus(parentvar) )
6923  {
6925  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6926  break;
6927 
6928  case SCIP_VARSTATUS_COLUMN:
6929  case SCIP_VARSTATUS_LOOSE:
6930  case SCIP_VARSTATUS_FIXED:
6932  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6933  return SCIP_INVALIDDATA;
6934 
6935  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6936  assert(parentvar->data.aggregate.var == var);
6937  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6938  {
6939  SCIP_Real parentnewbound;
6940 
6941  /* a > 0 -> change upper bound of y */
6942  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
6943  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6944  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6945  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6946  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6947  else
6948  parentnewbound = newbound;
6949  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6950  }
6951  else
6952  {
6953  SCIP_Real parentnewbound;
6954 
6955  /* a < 0 -> change lower bound of y */
6956  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6957  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
6958  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6959  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6960  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6961  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6962  else
6963  parentnewbound = -newbound;
6964  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6965  }
6966  break;
6967 
6968  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6969  assert(parentvar->negatedvar != NULL);
6970  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6971  assert(parentvar->negatedvar->negatedvar == parentvar);
6972  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6973  parentvar->data.negate.constant - newbound) );
6974  break;
6975 
6976  default:
6977  SCIPerrorMessage("unknown variable status\n");
6978  return SCIP_INVALIDDATA;
6979  }
6980  }
6981 
6982  return SCIP_OKAY;
6983 }
6984 
6985 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6986  * updates local lower bound if the global bound is tighter
6987  */
6989  SCIP_VAR* var, /**< problem variable to change */
6990  BMS_BLKMEM* blkmem, /**< block memory */
6991  SCIP_SET* set, /**< global SCIP settings */
6992  SCIP_STAT* stat, /**< problem statistics */
6993  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6994  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6995  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6996  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6997  SCIP_Real newbound /**< new bound for variable */
6998  )
6999 {
7000  assert(var != NULL);
7001  assert(blkmem != NULL);
7002  assert(set != NULL);
7003  assert(var->scip == set->scip);
7004 
7005  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7006  * of the domain within feastol
7007  */
7008  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7009 
7010  /* adjust bound to integral value if variable is of integral type */
7011  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7012 
7013  /* check that the adjusted bound is feasible
7014  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7015  * here because we reset bounds to their original value!
7016  */
7017  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7018 
7019  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7020  {
7021  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7022  newbound = MIN(newbound, var->glbdom.ub);
7023  }
7024  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7025 
7026  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7027  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7028  */
7029  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7030 
7031  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7032 
7033  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7034  return SCIP_OKAY;
7035 
7036  /* change bounds of attached variables */
7037  switch( SCIPvarGetStatus(var) )
7038  {
7040  if( var->data.original.transvar != NULL )
7041  {
7042  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7043  cliquetable, newbound) );
7044  }
7045  else
7046  {
7047  assert(set->stage == SCIP_STAGE_PROBLEM);
7048  if( newbound > SCIPvarGetLbLocal(var) )
7049  {
7050  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7051  }
7052  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7053  }
7054  break;
7055 
7056  case SCIP_VARSTATUS_COLUMN:
7057  case SCIP_VARSTATUS_LOOSE:
7058  if( newbound > SCIPvarGetLbLocal(var) )
7059  {
7060  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7061  }
7062  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7063  break;
7064 
7065  case SCIP_VARSTATUS_FIXED:
7066  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7067  return SCIP_INVALIDDATA;
7068 
7069  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7070  assert(var->data.aggregate.var != NULL);
7071  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7072  {
7073  SCIP_Real childnewbound;
7074 
7075  /* a > 0 -> change lower bound of y */
7076  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7077  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7079  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7080  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7081  else
7082  childnewbound = newbound;
7083  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7084  childnewbound) );
7085  }
7086  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7087  {
7088  SCIP_Real childnewbound;
7089 
7090  /* a < 0 -> change upper bound of y */
7091  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7092  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7094  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7095  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7096  else
7097  childnewbound = -newbound;
7098  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7099  childnewbound) );
7100  }
7101  else
7102  {
7103  SCIPerrorMessage("scalar is zero in aggregation\n");
7104  return SCIP_INVALIDDATA;
7105  }
7106  break;
7107 
7109  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7110  return SCIP_INVALIDDATA;
7111 
7112  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7113  assert(var->negatedvar != NULL);
7115  assert(var->negatedvar->negatedvar == var);
7116  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7117  var->data.negate.constant - newbound) );
7118  break;
7119 
7120  default:
7121  SCIPerrorMessage("unknown variable status\n");
7122  return SCIP_INVALIDDATA;
7123  }
7124 
7125  return SCIP_OKAY;
7126 }
7127 
7128 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7129  * updates local upper bound if the global bound is tighter
7130  */
7132  SCIP_VAR* var, /**< problem variable to change */
7133  BMS_BLKMEM* blkmem, /**< block memory */
7134  SCIP_SET* set, /**< global SCIP settings */
7135  SCIP_STAT* stat, /**< problem statistics */
7136  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7137  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7138  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7139  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7140  SCIP_Real newbound /**< new bound for variable */
7141  )
7142 {
7143  assert(var != NULL);
7144  assert(blkmem != NULL);
7145  assert(set != NULL);
7146  assert(var->scip == set->scip);
7147 
7148  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7149  * of the domain within feastol
7150  */
7151  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7152 
7153  /* adjust bound to integral value if variable is of integral type */
7154  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7155 
7156  /* check that the adjusted bound is feasible
7157  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7158  * here because we reset bounds to their original value!
7159  */
7160  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7161 
7162  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7163  {
7164  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7165  newbound = MAX(newbound, var->glbdom.lb);
7166  }
7167  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7168 
7169  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7170  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7171  */
7172  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7173 
7174  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7175 
7176  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7177  return SCIP_OKAY;
7178 
7179  /* change bounds of attached variables */
7180  switch( SCIPvarGetStatus(var) )
7181  {
7183  if( var->data.original.transvar != NULL )
7184  {
7185  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7186  newbound) );
7187  }
7188  else
7189  {
7190  assert(set->stage == SCIP_STAGE_PROBLEM);
7191  if( newbound < SCIPvarGetUbLocal(var) )
7192  {
7193  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7194  }
7195  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7196  }
7197  break;
7198 
7199  case SCIP_VARSTATUS_COLUMN:
7200  case SCIP_VARSTATUS_LOOSE:
7201  if( newbound < SCIPvarGetUbLocal(var) )
7202  {
7203  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7204  }
7205  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7206  break;
7207 
7208  case SCIP_VARSTATUS_FIXED:
7209  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7210  return SCIP_INVALIDDATA;
7211 
7212  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7213  assert(var->data.aggregate.var != NULL);
7214  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7215  {
7216  SCIP_Real childnewbound;
7217 
7218  /* a > 0 -> change lower bound of y */
7219  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7220  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7222  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7223  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7224  else
7225  childnewbound = newbound;
7226  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7227  childnewbound) );
7228  }
7229  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7230  {
7231  SCIP_Real childnewbound;
7232 
7233  /* a < 0 -> change upper bound of y */
7234  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7235  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7237  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7238  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7239  else
7240  childnewbound = -newbound;
7241  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7242  childnewbound) );
7243  }
7244  else
7245  {
7246  SCIPerrorMessage("scalar is zero in aggregation\n");
7247  return SCIP_INVALIDDATA;
7248  }
7249  break;
7250 
7252  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7253  return SCIP_INVALIDDATA;
7254 
7255  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7256  assert(var->negatedvar != NULL);
7258  assert(var->negatedvar->negatedvar == var);
7259  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7260  var->data.negate.constant - newbound) );
7261  break;
7262 
7263  default:
7264  SCIPerrorMessage("unknown variable status\n");
7265  return SCIP_INVALIDDATA;
7266  }
7267 
7268  return SCIP_OKAY;
7269 }
7270 
7271 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7273  SCIP_VAR* var, /**< problem variable */
7274  SCIP_SET* set, /**< global SCIP settings */
7275  SCIP_Real lazylb /**< the lazy lower bound to be set */
7276  )
7277 {
7278  assert(var != NULL);
7279  assert(var->probindex != -1);
7280  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7281  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7282  assert(set != NULL);
7283  assert(var->scip == set->scip);
7284 
7285  /* variable should not be in the LP */
7287  return SCIP_INVALIDCALL;
7288 
7289  var->lazylb = lazylb;
7290 
7291  return SCIP_OKAY;
7292 }
7293 
7294 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7296  SCIP_VAR* var, /**< problem variable */
7297  SCIP_SET* set, /**< global SCIP settings */
7298  SCIP_Real lazyub /**< the lazy lower bound to be set */
7299  )
7300 {
7301  assert(var != NULL);
7302  assert(var->probindex != -1);
7303  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7304  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7305  assert(set != NULL);
7306  assert(var->scip == set->scip);
7307 
7308  /* variable should not be in the LP */
7310  return SCIP_INVALIDCALL;
7311 
7312  var->lazyub = lazyub;
7313 
7314  return SCIP_OKAY;
7315 }
7316 
7317 
7318 /** changes global bound of variable; if possible, adjusts bound to integral value;
7319  * updates local bound if the global bound is tighter
7320  */
7322  SCIP_VAR* var, /**< problem variable to change */
7323  BMS_BLKMEM* blkmem, /**< block memory */
7324  SCIP_SET* set, /**< global SCIP settings */
7325  SCIP_STAT* stat, /**< problem statistics */
7326  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7327  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7328  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7329  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7330  SCIP_Real newbound, /**< new bound for variable */
7331  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7332  )
7333 {
7334  /* apply bound change to the LP data */
7335  switch( boundtype )
7336  {
7337  case SCIP_BOUNDTYPE_LOWER:
7338  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7339  case SCIP_BOUNDTYPE_UPPER:
7340  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7341  default:
7342  SCIPerrorMessage("unknown bound type\n");
7343  return SCIP_INVALIDDATA;
7344  }
7345 }
7346 
7347 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7348 static
7350  SCIP_VAR* var, /**< problem variable to change */
7351  BMS_BLKMEM* blkmem, /**< block memory */
7352  SCIP_SET* set, /**< global SCIP settings */
7353  SCIP_LP* lp, /**< current LP data */
7354  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7355  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7356  SCIP_Real oldbound, /**< old lower bound for variable */
7357  SCIP_Real newbound /**< new lower bound for variable */
7358  )
7359 {
7360  assert(var != NULL);
7361  assert(var->eventfilter != NULL);
7362  assert(SCIPvarIsTransformed(var));
7363  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7364  assert(set != NULL);
7365  assert(var->scip == set->scip);
7366 
7367  /* check, if the variable is being tracked for bound changes
7368  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7369  */
7370  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7373  {
7374  SCIP_EVENT* event;
7375 
7376  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7377 
7378  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7379  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7380  }
7381 
7382  return SCIP_OKAY;
7383 }
7384 
7385 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7386 static
7388  SCIP_VAR* var, /**< problem variable to change */
7389  BMS_BLKMEM* blkmem, /**< block memory */
7390  SCIP_SET* set, /**< global SCIP settings */
7391  SCIP_LP* lp, /**< current LP data */
7392  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7393  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7394  SCIP_Real oldbound, /**< old upper bound for variable */
7395  SCIP_Real newbound /**< new upper bound for variable */
7396  )
7397 {
7398  assert(var != NULL);
7399  assert(var->eventfilter != NULL);
7400  assert(SCIPvarIsTransformed(var));
7401  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7402  assert(set != NULL);
7403  assert(var->scip == set->scip);
7404 
7405  /* check, if the variable is being tracked for bound changes
7406  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7407  */
7408  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7411  {
7412  SCIP_EVENT* event;
7413 
7414  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7415 
7416  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7417  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7418  }
7419 
7420  return SCIP_OKAY;
7421 }
7422 
7423 /* forward declaration, because both methods call each other recursively */
7424 
7425 /* performs the current change in upper bound, changes all parents accordingly */
7426 static
7428  SCIP_VAR* var, /**< problem variable to change */
7429  BMS_BLKMEM* blkmem, /**< block memory */
7430  SCIP_SET* set, /**< global SCIP settings */
7431  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7432  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7433  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7434  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7435  SCIP_Real newbound /**< new bound for variable */
7436  );
7437 
7438 /** performs the current change in lower bound, changes all parents accordingly */
7439 static
7441  SCIP_VAR* var, /**< problem variable to change */
7442  BMS_BLKMEM* blkmem, /**< block memory */
7443  SCIP_SET* set, /**< global SCIP settings */
7444  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7445  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7446  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7447  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7448  SCIP_Real newbound /**< new bound for variable */
7449  )
7450 {
7451  SCIP_VAR* parentvar;
7452  SCIP_Real oldbound;
7453  int i;
7454 
7455  assert(var != NULL);
7456  assert(set != NULL);
7457  assert(var->scip == set->scip);
7458  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7459  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7460  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7461  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7463 
7464  /* check that the bound is feasible */
7465  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7466  /* adjust bound to integral value if variable is of integral type */
7467  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7468 
7469  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7470  {
7471  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7472  newbound = MIN(newbound, var->locdom.ub);
7473 
7474  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7475  newbound = MAX(newbound, var->glbdom.lb);
7476  }
7477  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7478 
7479  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7480 
7481  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7482  newbound = var->glbdom.lb;
7483  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7484  return SCIP_OKAY;
7485 
7486  /* change the bound */
7487  oldbound = var->locdom.lb;
7488  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7489  var->locdom.lb = newbound;
7490 
7491  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7492  * once update the statistic
7493  */
7494  if( stat != NULL )
7495  SCIPstatIncrement(stat, set, domchgcount);
7496 
7497  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7498  {
7499  /* merges overlapping holes into single holes, moves bounds respectively */
7500  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7501  }
7502 
7503  /* issue bound change event */
7504  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7505  if( var->eventfilter != NULL )
7506  {
7507  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7508  }
7509 
7510  /* process parent variables */
7511  for( i = 0; i < var->nparentvars; ++i )
7512  {
7513  parentvar = var->parentvars[i];
7514  assert(parentvar != NULL);
7515 
7516  switch( SCIPvarGetStatus(parentvar) )
7517  {
7519  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7520  break;
7521 
7522  case SCIP_VARSTATUS_COLUMN:
7523  case SCIP_VARSTATUS_LOOSE:
7524  case SCIP_VARSTATUS_FIXED:
7526  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7527  return SCIP_INVALIDDATA;
7528 
7529  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7530  assert(parentvar->data.aggregate.var == var);
7531  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7532  {
7533  SCIP_Real parentnewbound;
7534 
7535  /* a > 0 -> change lower bound of y */
7536  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7537  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7538  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7539 
7540  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7541  {
7542  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7543  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7544  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7545  * as a result, the parent's lower bound is set to it's upper bound, and not above
7546  */
7547  if( parentnewbound > parentvar->glbdom.ub )
7548  {
7549  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7550  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7551  parentnewbound = parentvar->glbdom.ub;
7552  }
7553  }
7554  else
7555  parentnewbound = newbound;
7556  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7557  }
7558  else
7559  {
7560  SCIP_Real parentnewbound;
7561 
7562  /* a < 0 -> change upper bound of y */
7563  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7564  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7565  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7566  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7567 
7568  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7569  {
7570  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7571  /* 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
7572  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7573  * as a result, the parent's upper bound is set to it's lower bound, and not below
7574  */
7575  if( parentnewbound < parentvar->glbdom.lb )
7576  {
7577  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7578  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7579  parentnewbound = parentvar->glbdom.lb;
7580  }
7581  }
7582  else
7583  parentnewbound = -newbound;
7584  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7585  }
7586  break;
7587 
7588  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7589  assert(parentvar->negatedvar != NULL);
7590  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7591  assert(parentvar->negatedvar->negatedvar == parentvar);
7592  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7593  parentvar->data.negate.constant - newbound) );
7594  break;
7595 
7596  default:
7597  SCIPerrorMessage("unknown variable status\n");
7598  return SCIP_INVALIDDATA;
7599  }
7600  }
7601 
7602  return SCIP_OKAY;
7603 }
7604 
7605 /** performs the current change in upper bound, changes all parents accordingly */
7606 static
7608  SCIP_VAR* var, /**< problem variable to change */
7609  BMS_BLKMEM* blkmem, /**< block memory */
7610  SCIP_SET* set, /**< global SCIP settings */
7611  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7612  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7613  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7614  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7615  SCIP_Real newbound /**< new bound for variable */
7616  )
7617 {
7618  SCIP_VAR* parentvar;
7619  SCIP_Real oldbound;
7620  int i;
7621 
7622  assert(var != NULL);
7623  assert(set != NULL);
7624  assert(var->scip == set->scip);
7625  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7626  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7627  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7628  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7630 
7631  /* check that the bound is feasible */
7632  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7633  /* adjust bound to integral value if variable is of integral type */
7634  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7635 
7636  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7637  {
7638  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7639  newbound = MAX(newbound, var->locdom.lb);
7640 
7641  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7642  newbound = MIN(newbound, var->glbdom.ub);
7643  }
7644  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7645 
7646  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7647 
7648  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7649  newbound = var->glbdom.ub;
7650  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7651  return SCIP_OKAY;
7652 
7653  /* change the bound */
7654  oldbound = var->locdom.ub;
7655  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7656  var->locdom.ub = newbound;
7657 
7658  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7659  * once update the statistic
7660  */
7661  if( stat != NULL )
7662  SCIPstatIncrement(stat, set, domchgcount);
7663 
7664  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7665  {
7666  /* merges overlapping holes into single holes, moves bounds respectively */
7667  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7668  }
7669 
7670  /* issue bound change event */
7671  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7672  if( var->eventfilter != NULL )
7673  {
7674  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7675  }
7676 
7677  /* process parent variables */
7678  for( i = 0; i < var->nparentvars; ++i )
7679  {
7680  parentvar = var->parentvars[i];
7681  assert(parentvar != NULL);
7682 
7683  switch( SCIPvarGetStatus(parentvar) )
7684  {
7686  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7687  break;
7688 
7689  case SCIP_VARSTATUS_COLUMN:
7690  case SCIP_VARSTATUS_LOOSE:
7691  case SCIP_VARSTATUS_FIXED:
7693  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7694  return SCIP_INVALIDDATA;
7695 
7696  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7697  assert(parentvar->data.aggregate.var == var);
7698  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7699  {
7700  SCIP_Real parentnewbound;
7701 
7702  /* a > 0 -> change upper bound of x */
7703  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7704  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7705  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7706  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7707  {
7708  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7709  /* 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
7710  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7711  * as a result, the parent's upper bound is set to it's lower bound, and not below
7712  */
7713  if( parentnewbound < parentvar->glbdom.lb )
7714  {
7715  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7716  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7717  parentnewbound = parentvar->glbdom.lb;
7718  }
7719  }
7720  else
7721  parentnewbound = newbound;
7722  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7723  }
7724  else
7725  {
7726  SCIP_Real parentnewbound;
7727 
7728  /* a < 0 -> change lower bound of x */
7729  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7730  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7731  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7732  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7733  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7734  {
7735  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7736  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7737  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7738  * as a result, the parent's lower bound is set to it's upper bound, and not above
7739  */
7740  if( parentnewbound > parentvar->glbdom.ub )
7741  {
7742  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7743  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7744  parentnewbound = parentvar->glbdom.ub;
7745  }
7746  }
7747  else
7748  parentnewbound = -newbound;
7749  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7750  }
7751  break;
7752 
7753  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7754  assert(parentvar->negatedvar != NULL);
7755  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7756  assert(parentvar->negatedvar->negatedvar == parentvar);
7757  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7758  parentvar->data.negate.constant - newbound) );
7759  break;
7760 
7761  default:
7762  SCIPerrorMessage("unknown variable status\n");
7763  return SCIP_INVALIDDATA;
7764  }
7765  }
7766 
7767  return SCIP_OKAY;
7768 }
7769 
7770 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7771  * information in variable
7772  */
7774  SCIP_VAR* var, /**< problem variable to change */
7775  BMS_BLKMEM* blkmem, /**< block memory */
7776  SCIP_SET* set, /**< global SCIP settings */
7777  SCIP_STAT* stat, /**< problem statistics */
7778  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7779  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7780  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7781  SCIP_Real newbound /**< new bound for variable */
7782  )
7783 {
7784  assert(var != NULL);
7785  assert(blkmem != NULL);
7786  assert(set != NULL);
7787  assert(var->scip == set->scip);
7788 
7789  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7790  * of the domain within feastol
7791  */
7792  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7793 
7794  /* adjust bound to integral value if variable is of integral type */
7795  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7796 
7797  /* check that the adjusted bound is feasible */
7798  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7799 
7800  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7801  {
7802  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7803  newbound = MIN(newbound, var->locdom.ub);
7804  }
7805  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7806 
7807  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7808 
7809  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
7810  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7811  return SCIP_OKAY;
7812 
7813  /* change bounds of attached variables */
7814  switch( SCIPvarGetStatus(var) )
7815  {
7817  if( var->data.original.transvar != NULL )
7818  {
7819  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7820  newbound) );
7821  }
7822  else
7823  {
7824  assert(set->stage == SCIP_STAGE_PROBLEM);
7825  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7826  }
7827  break;
7828 
7829  case SCIP_VARSTATUS_COLUMN:
7830  case SCIP_VARSTATUS_LOOSE:
7831  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7832  break;
7833 
7834  case SCIP_VARSTATUS_FIXED:
7835  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7836  return SCIP_INVALIDDATA;
7837 
7838  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7839  assert(var->data.aggregate.var != NULL);
7840  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7841  {
7842  SCIP_Real childnewbound;
7843 
7844  /* a > 0 -> change lower bound of y */
7845  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7846  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7848  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7849  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7850  else
7851  childnewbound = newbound;
7852  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7853  childnewbound) );
7854  }
7855  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7856  {
7857  SCIP_Real childnewbound;
7858 
7859  /* a < 0 -> change upper bound of y */
7860  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7861  || SCIPsetIsFeasEQ(set, var->locdom.lb,
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( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7868  childnewbound) );
7869  }
7870  else
7871  {
7872  SCIPerrorMessage("scalar is zero in aggregation\n");
7873  return SCIP_INVALIDDATA;
7874  }
7875  break;
7876 
7878  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7879  return SCIP_INVALIDDATA;
7880 
7881  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7882  assert(var->negatedvar != NULL);
7884  assert(var->negatedvar->negatedvar == var);
7885  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7886  var->data.negate.constant - newbound) );
7887  break;
7888 
7889  default:
7890  SCIPerrorMessage("unknown variable status\n");
7891  return SCIP_INVALIDDATA;
7892  }
7893 
7894  return SCIP_OKAY;
7895 }
7896 
7897 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7898  * information in variable
7899  */
7901  SCIP_VAR* var, /**< problem variable to change */
7902  BMS_BLKMEM* blkmem, /**< block memory */
7903  SCIP_SET* set, /**< global SCIP settings */
7904  SCIP_STAT* stat, /**< problem statistics */
7905  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7906  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7907  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7908  SCIP_Real newbound /**< new bound for variable */
7909  )
7910 {
7911  assert(var != NULL);
7912  assert(blkmem != NULL);
7913  assert(set != NULL);
7914  assert(var->scip == set->scip);
7915 
7916  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7917  * of the domain within feastol
7918  */
7919  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7920 
7921  /* adjust bound to integral value if variable is of integral type */
7922  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7923 
7924  /* check that the adjusted bound is feasible */
7925  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7926 
7927  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7928  {
7929  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7930  newbound = MAX(newbound, var->locdom.lb);
7931  }
7932  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7933 
7934  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7935 
7936  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
7937  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7938  return SCIP_OKAY;
7939 
7940  /* change bounds of attached variables */
7941  switch( SCIPvarGetStatus(var) )
7942  {
7944  if( var->data.original.transvar != NULL )
7945  {
7946  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7947  }
7948  else
7949  {
7950  assert(set->stage == SCIP_STAGE_PROBLEM);
7951  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7952  }
7953  break;
7954 
7955  case SCIP_VARSTATUS_COLUMN:
7956  case SCIP_VARSTATUS_LOOSE:
7957  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7958  break;
7959 
7960  case SCIP_VARSTATUS_FIXED:
7961  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7962  return SCIP_INVALIDDATA;
7963 
7964  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7965  assert(var->data.aggregate.var != NULL);
7966  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7967  {
7968  SCIP_Real childnewbound;
7969 
7970  /* a > 0 -> change upper bound of y */
7971  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7972  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7974  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7975  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7976  else
7977  childnewbound = newbound;
7978  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7979  childnewbound) );
7980  }
7981  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7982  {
7983  SCIP_Real childnewbound;
7984 
7985  /* a < 0 -> change lower bound of y */
7986  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7987  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7989  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7990  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7991  else
7992  childnewbound = -newbound;
7993  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7994  childnewbound) );
7995  }
7996  else
7997  {
7998  SCIPerrorMessage("scalar is zero in aggregation\n");
7999  return SCIP_INVALIDDATA;
8000  }
8001  break;
8002 
8004  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8005  return SCIP_INVALIDDATA;
8006 
8007  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8008  assert(var->negatedvar != NULL);
8010  assert(var->negatedvar->negatedvar == var);
8011  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8012  var->data.negate.constant - newbound) );
8013  break;
8014 
8015  default:
8016  SCIPerrorMessage("unknown variable status\n");
8017  return SCIP_INVALIDDATA;
8018  }
8019 
8020  return SCIP_OKAY;
8021 }
8022 
8023 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8024  * information in variable
8025  */
8027  SCIP_VAR* var, /**< problem variable to change */
8028  BMS_BLKMEM* blkmem, /**< block memory */
8029  SCIP_SET* set, /**< global SCIP settings */
8030  SCIP_STAT* stat, /**< problem statistics */
8031  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8032  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8033  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8034  SCIP_Real newbound, /**< new bound for variable */
8035  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8036  )
8037 {
8038  /* apply bound change to the LP data */
8039  switch( boundtype )
8040  {
8041  case SCIP_BOUNDTYPE_LOWER:
8042  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8043  case SCIP_BOUNDTYPE_UPPER:
8044  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8045  default:
8046  SCIPerrorMessage("unknown bound type\n");
8047  return SCIP_INVALIDDATA;
8048  }
8049 }
8050 
8051 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8053  SCIP_VAR* var, /**< problem variable to change */
8054  SCIP_SET* set, /**< global SCIP settings */
8055  SCIP_LP* lp, /**< current LP data */
8056  SCIP_Real newbound /**< new bound for variable */
8057  )
8058 {
8059  assert(var != NULL);
8060  assert(set != NULL);
8061  assert(var->scip == set->scip);
8062  assert(lp != NULL);
8063  assert(SCIPlpDiving(lp));
8064 
8065  /* adjust bound for integral variables */
8066  SCIPvarAdjustLb(var, set, &newbound);
8067 
8068  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8069 
8070  /* change bounds of attached variables */
8071  switch( SCIPvarGetStatus(var) )
8072  {
8074  assert(var->data.original.transvar != NULL);
8075  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8076  break;
8077 
8078  case SCIP_VARSTATUS_COLUMN:
8079  assert(var->data.col != NULL);
8080  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8081  break;
8082 
8083  case SCIP_VARSTATUS_LOOSE:
8084  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8085  return SCIP_INVALIDDATA;
8086 
8087  case SCIP_VARSTATUS_FIXED:
8088  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8089  return SCIP_INVALIDDATA;
8090 
8091  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8092  assert(var->data.aggregate.var != NULL);
8093  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8094  {
8095  SCIP_Real childnewbound;
8096 
8097  /* a > 0 -> change lower bound of y */
8098  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8099  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8100  else
8101  childnewbound = newbound;
8102  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8103  }
8104  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8105  {
8106  SCIP_Real childnewbound;
8107 
8108  /* a < 0 -> change upper bound of y */
8109  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8110  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8111  else
8112  childnewbound = -newbound;
8113  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8114  }
8115  else
8116  {
8117  SCIPerrorMessage("scalar is zero in aggregation\n");
8118  return SCIP_INVALIDDATA;
8119  }
8120  break;
8121 
8123  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8124  return SCIP_INVALIDDATA;
8125 
8126  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8127  assert(var->negatedvar != NULL);
8129  assert(var->negatedvar->negatedvar == var);
8130  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8131  break;
8132 
8133  default:
8134  SCIPerrorMessage("unknown variable status\n");
8135  return SCIP_INVALIDDATA;
8136  }
8137 
8138  return SCIP_OKAY;
8139 }
8140 
8141 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8143  SCIP_VAR* var, /**< problem variable to change */
8144  SCIP_SET* set, /**< global SCIP settings */
8145  SCIP_LP* lp, /**< current LP data */
8146  SCIP_Real newbound /**< new bound for variable */
8147  )
8148 {
8149  assert(var != NULL);
8150  assert(set != NULL);
8151  assert(var->scip == set->scip);
8152  assert(lp != NULL);
8153  assert(SCIPlpDiving(lp));
8154 
8155  /* adjust bound for integral variables */
8156  SCIPvarAdjustUb(var, set, &newbound);
8157 
8158  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8159 
8160  /* change bounds of attached variables */
8161  switch( SCIPvarGetStatus(var) )
8162  {
8164  assert(var->data.original.transvar != NULL);
8165  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8166  break;
8167 
8168  case SCIP_VARSTATUS_COLUMN:
8169  assert(var->data.col != NULL);
8170  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8171  break;
8172 
8173  case SCIP_VARSTATUS_LOOSE:
8174  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8175  return SCIP_INVALIDDATA;
8176 
8177  case SCIP_VARSTATUS_FIXED:
8178  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8179  return SCIP_INVALIDDATA;
8180 
8181  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8182  assert(var->data.aggregate.var != NULL);
8183  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8184  {
8185  SCIP_Real childnewbound;
8186 
8187  /* a > 0 -> change upper bound of y */
8188  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8189  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8190  else
8191  childnewbound = newbound;
8192  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8193  }
8194  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8195  {
8196  SCIP_Real childnewbound;
8197 
8198  /* a < 0 -> change lower bound of y */
8199  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8200  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8201  else
8202  childnewbound = -newbound;
8203  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8204  }
8205  else
8206  {
8207  SCIPerrorMessage("scalar is zero in aggregation\n");
8208  return SCIP_INVALIDDATA;
8209  }
8210  break;
8211 
8213  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8214  return SCIP_INVALIDDATA;
8215 
8216  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8217  assert(var->negatedvar != NULL);
8219  assert(var->negatedvar->negatedvar == var);
8220  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8221  break;
8222 
8223  default:
8224  SCIPerrorMessage("unknown variable status\n");
8225  return SCIP_INVALIDDATA;
8226  }
8227 
8228  return SCIP_OKAY;
8229 }
8230 
8231 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8232  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8233  * not updated if bounds of aggregation variables are changing
8234  *
8235  * calling this function for a non-multi-aggregated variable is not allowed
8236  */
8238  SCIP_VAR* var, /**< problem variable */
8239  SCIP_SET* set /**< global SCIP settings */
8240  )
8241 {
8242  int i;
8243  SCIP_Real lb;
8244  SCIP_Real bnd;
8245  SCIP_VAR* aggrvar;
8246  SCIP_Bool posinf;
8247  SCIP_Bool neginf;
8248 
8249  assert(var != NULL);
8250  assert(set != NULL);
8251  assert(var->scip == set->scip);
8253 
8254  posinf = FALSE;
8255  neginf = FALSE;
8256  lb = var->data.multaggr.constant;
8257  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8258  {
8259  aggrvar = var->data.multaggr.vars[i];
8260  if( var->data.multaggr.scalars[i] > 0.0 )
8261  {
8262  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8263 
8264  if( SCIPsetIsInfinity(set, bnd) )
8265  posinf = TRUE;
8266  else if( SCIPsetIsInfinity(set, -bnd) )
8267  neginf = TRUE;
8268  else
8269  lb += var->data.multaggr.scalars[i] * bnd;
8270  }
8271  else
8272  {
8273  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8274 
8275  if( SCIPsetIsInfinity(set, -bnd) )
8276  posinf = TRUE;
8277  else if( SCIPsetIsInfinity(set, bnd) )
8278  neginf = TRUE;
8279  else
8280  lb += var->data.multaggr.scalars[i] * bnd;
8281  }
8282 
8283  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8284  * variable
8285  */
8286  if( neginf )
8287  return SCIPvarGetLbLocal(var);
8288  }
8289 
8290  /* if positive infinity flag was set to true return infinity */
8291  if( posinf )
8292  return SCIPsetInfinity(set);
8293 
8294  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8295 }
8296 
8297 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8298  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8299  * not updated if bounds of aggregation variables are changing
8300  *
8301  * calling this function for a non-multi-aggregated variable is not allowed
8302  */
8304  SCIP_VAR* var, /**< problem variable */
8305  SCIP_SET* set /**< global SCIP settings */
8306  )
8307 {
8308  int i;
8309  SCIP_Real ub;
8310  SCIP_Real bnd;
8311  SCIP_VAR* aggrvar;
8312  SCIP_Bool posinf;
8313  SCIP_Bool neginf;
8314 
8315  assert(var != NULL);
8316  assert(set != NULL);
8317  assert(var->scip == set->scip);
8319 
8320  posinf = FALSE;
8321  neginf = FALSE;
8322  ub = var->data.multaggr.constant;
8323  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8324  {
8325  aggrvar = var->data.multaggr.vars[i];
8326  if( var->data.multaggr.scalars[i] > 0.0 )
8327  {
8328  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8329 
8330  if( SCIPsetIsInfinity(set, bnd) )
8331  posinf = TRUE;
8332  else if( SCIPsetIsInfinity(set, -bnd) )
8333  neginf = TRUE;
8334  else
8335  ub += var->data.multaggr.scalars[i] * bnd;
8336  }
8337  else
8338  {
8339  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8340 
8341  if( SCIPsetIsInfinity(set, -bnd) )
8342  posinf = TRUE;
8343  else if( SCIPsetIsInfinity(set, bnd) )
8344  neginf = TRUE;
8345  else
8346  ub += var->data.multaggr.scalars[i] * bnd;
8347  }
8348 
8349  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8350  * variable
8351  */
8352  if( posinf )
8353  return SCIPvarGetUbLocal(var);
8354  }
8355 
8356  /* if negative infinity flag was set to true return -infinity */
8357  if( neginf )
8358  return -SCIPsetInfinity(set);
8359 
8360  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8361 }
8362 
8363 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8364  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8365  * not updated if bounds of aggregation variables are changing
8366  *
8367  * calling this function for a non-multi-aggregated variable is not allowed
8368  */
8370  SCIP_VAR* var, /**< problem variable */
8371  SCIP_SET* set /**< global SCIP settings */
8372  )
8373 {
8374  int i;
8375  SCIP_Real lb;
8376  SCIP_Real bnd;
8377  SCIP_VAR* aggrvar;
8378  SCIP_Bool posinf;
8379  SCIP_Bool neginf;
8380 
8381  assert(var != NULL);
8382  assert(set != NULL);
8383  assert(var->scip == set->scip);
8385 
8386  posinf = FALSE;
8387  neginf = FALSE;
8388  lb = var->data.multaggr.constant;
8389  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8390  {
8391  aggrvar = var->data.multaggr.vars[i];
8392  if( var->data.multaggr.scalars[i] > 0.0 )
8393  {
8394  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8395 
8396  if( SCIPsetIsInfinity(set, bnd) )
8397  posinf = TRUE;
8398  else if( SCIPsetIsInfinity(set, -bnd) )
8399  neginf = TRUE;
8400  else
8401  lb += var->data.multaggr.scalars[i] * bnd;
8402  }
8403  else
8404  {
8405  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8406 
8407  if( SCIPsetIsInfinity(set, -bnd) )
8408  posinf = TRUE;
8409  else if( SCIPsetIsInfinity(set, bnd) )
8410  neginf = TRUE;
8411  else
8412  lb += var->data.multaggr.scalars[i] * bnd;
8413  }
8414 
8415  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8416  * variable
8417  */
8418  if( neginf )
8419  return SCIPvarGetLbGlobal(var);
8420  }
8421 
8422  /* if positive infinity flag was set to true return infinity */
8423  if( posinf )
8424  return SCIPsetInfinity(set);
8425 
8426  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8427 }
8428 
8429 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8430  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8431  * not updated if bounds of aggregation variables are changing
8432  *
8433  * calling this function for a non-multi-aggregated variable is not allowed
8434  */
8436  SCIP_VAR* var, /**< problem variable */
8437  SCIP_SET* set /**< global SCIP settings */
8438  )
8439 {
8440  int i;
8441  SCIP_Real ub;
8442  SCIP_Real bnd;
8443  SCIP_VAR* aggrvar;
8444  SCIP_Bool posinf;
8445  SCIP_Bool neginf;
8446 
8447  assert(var != NULL);
8448  assert(set != NULL);
8449  assert(var->scip == set->scip);
8451 
8452  posinf = FALSE;
8453  neginf = FALSE;
8454  ub = var->data.multaggr.constant;
8455  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8456  {
8457  aggrvar = var->data.multaggr.vars[i];
8458  if( var->data.multaggr.scalars[i] > 0.0 )
8459  {
8460  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8461 
8462  if( SCIPsetIsInfinity(set, bnd) )
8463  posinf = TRUE;
8464  else if( SCIPsetIsInfinity(set, -bnd) )
8465  neginf = TRUE;
8466  else
8467  ub += var->data.multaggr.scalars[i] * bnd;
8468  }
8469  else
8470  {
8471  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8472 
8473  if( SCIPsetIsInfinity(set, -bnd) )
8474  posinf = TRUE;
8475  else if( SCIPsetIsInfinity(set, bnd) )
8476  neginf = TRUE;
8477  else
8478  ub += var->data.multaggr.scalars[i] * bnd;
8479  }
8480 
8481  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8482  * variable
8483  */
8484  if( posinf )
8485  return SCIPvarGetUbGlobal(var);
8486  }
8487 
8488  /* if negative infinity flag was set to true return -infinity */
8489  if( neginf )
8490  return -SCIPsetInfinity(set);
8491 
8492  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8493 }
8494 
8495 /** adds a hole to the original domain of the variable */
8497  SCIP_VAR* var, /**< problem variable */
8498  BMS_BLKMEM* blkmem, /**< block memory */
8499  SCIP_SET* set, /**< global SCIP settings */
8500  SCIP_Real left, /**< left bound of open interval in new hole */
8501  SCIP_Real right /**< right bound of open interval in new hole */
8502  )
8503 {
8504  SCIP_Bool added;
8505 
8506  assert(var != NULL);
8507  assert(!SCIPvarIsTransformed(var));
8509  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8510  assert(set != NULL);
8511  assert(var->scip == set->scip);
8512  assert(set->stage == SCIP_STAGE_PROBLEM);
8513 
8514  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8515 
8516  if( SCIPsetIsEQ(set, left, right) )
8517  return SCIP_OKAY;
8518 
8519  /* the interval should not be empty */
8520  assert(SCIPsetIsLT(set, left, right));
8521 
8522  /* the the interval bound should already be adjusted */
8523  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8524  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8525 
8526  /* the the interval should lay between the lower and upper bound */
8527  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8528  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8529 
8530  /* add domain hole */
8531  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8532 
8533  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8534  if( added )
8535  {
8536  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8537  }
8538 
8539  /**@todo add hole in parent and child variables (just like with bound changes);
8540  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8541  */
8542 
8543  return SCIP_OKAY;
8544 }
8545 
8546 /** performs the current add of domain, changes all parents accordingly */
8547 static
8549  SCIP_VAR* var, /**< problem variable */
8550  BMS_BLKMEM* blkmem, /**< block memory */
8551  SCIP_SET* set, /**< global SCIP settings */
8552  SCIP_STAT* stat, /**< problem statistics */
8553  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8554  SCIP_Real left, /**< left bound of open interval in new hole */
8555  SCIP_Real right, /**< right bound of open interval in new hole */
8556  SCIP_Bool* added /**< pointer to store whether the hole was added */
8557  )
8558 {
8559  SCIP_VAR* parentvar;
8560  SCIP_Real newlb;
8561  SCIP_Real newub;
8562  int i;
8563 
8564  assert(var != NULL);
8565  assert(added != NULL);
8566  assert(blkmem != NULL);
8567 
8568  /* the interval should not be empty */
8569  assert(SCIPsetIsLT(set, left, right));
8570 
8571  /* the interval bound should already be adjusted */
8572  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8573  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8574 
8575  /* the interval should lay between the lower and upper bound */
8576  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8577  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8578 
8579  /* @todo add debugging mechanism for holes when using a debugging solution */
8580 
8581  /* add hole to hole list */
8582  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8583 
8584  /* check if the hole is redundant */
8585  if( !(*added) )
8586  return SCIP_OKAY;
8587 
8588  /* current bounds */
8589  newlb = var->glbdom.lb;
8590  newub = var->glbdom.ub;
8591 
8592  /* merge domain holes */
8593  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8594 
8595  /* the bound should not be changed */
8596  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8597  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8598 
8599  /* issue bound change event */
8600  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8601  if( var->eventfilter != NULL )
8602  {
8603  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8604  }
8605 
8606  /* process parent variables */
8607  for( i = 0; i < var->nparentvars; ++i )
8608  {
8609  SCIP_Real parentnewleft;
8610  SCIP_Real parentnewright;
8611  SCIP_Bool localadded;
8612 
8613  parentvar = var->parentvars[i];
8614  assert(parentvar != NULL);
8615 
8616  switch( SCIPvarGetStatus(parentvar) )
8617  {
8619  parentnewleft = left;
8620  parentnewright = right;
8621  break;
8622 
8623  case SCIP_VARSTATUS_COLUMN:
8624  case SCIP_VARSTATUS_LOOSE:
8625  case SCIP_VARSTATUS_FIXED:
8627  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8628  return SCIP_INVALIDDATA;
8629 
8630  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8631  assert(parentvar->data.aggregate.var == var);
8632 
8633  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8634  {
8635  /* a > 0 -> change upper bound of x */
8636  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8637  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8638  }
8639  else
8640  {
8641  /* a < 0 -> change lower bound of x */
8642  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8643 
8644  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8645  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8646  }
8647  break;
8648 
8649  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8650  assert(parentvar->negatedvar != NULL);
8651  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8652  assert(parentvar->negatedvar->negatedvar == parentvar);
8653 
8654  parentnewright = -left + parentvar->data.negate.constant;
8655  parentnewleft = -right + parentvar->data.negate.constant;
8656  break;
8657 
8658  default:
8659  SCIPerrorMessage("unknown variable status\n");
8660  return SCIP_INVALIDDATA;
8661  }
8662 
8663  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8664 
8665  /* perform hole added for parent variable */
8666  assert(blkmem != NULL);
8667  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8668  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8669  parentnewleft, parentnewright, &localadded) );
8670  assert(localadded);
8671  }
8672 
8673  return SCIP_OKAY;
8674 }
8675 
8676 /** adds a hole to the variable's global and local domain */
8678  SCIP_VAR* var, /**< problem variable */
8679  BMS_BLKMEM* blkmem, /**< block memory */
8680  SCIP_SET* set, /**< global SCIP settings */
8681  SCIP_STAT* stat, /**< problem statistics */
8682  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8683  SCIP_Real left, /**< left bound of open interval in new hole */
8684  SCIP_Real right, /**< right bound of open interval in new hole */
8685  SCIP_Bool* added /**< pointer to store whether the hole was added */
8686  )
8687 {
8688  SCIP_Real childnewleft;
8689  SCIP_Real childnewright;
8690 
8691  assert(var != NULL);
8692  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8693  assert(blkmem != NULL);
8694  assert(added != NULL);
8695 
8696  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8697 
8698  /* the interval should not be empty */
8699  assert(SCIPsetIsLT(set, left, right));
8700 
8701  /* the the interval bound should already be adjusted */
8702  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8703  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8704 
8705  /* the the interval should lay between the lower and upper bound */
8706  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8707  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8708 
8709  /* change bounds of attached variables */
8710  switch( SCIPvarGetStatus(var) )
8711  {
8713  if( var->data.original.transvar != NULL )
8714  {
8715  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8716  left, right, added) );
8717  }
8718  else
8719  {
8720  assert(set->stage == SCIP_STAGE_PROBLEM);
8721 
8722  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8723  if( *added )
8724  {
8725  SCIP_Bool localadded;
8726 
8727  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8728  }
8729  }
8730  break;
8731 
8732  case SCIP_VARSTATUS_COLUMN:
8733  case SCIP_VARSTATUS_LOOSE:
8734  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8735  if( *added )
8736  {
8737  SCIP_Bool localadded;
8738 
8739  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8740  }
8741  break;
8742 
8743  case SCIP_VARSTATUS_FIXED:
8744  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8745  return SCIP_INVALIDDATA;
8746 
8747  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8748  assert(var->data.aggregate.var != NULL);
8749 
8750  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8751  {
8752  /* a > 0 -> change lower bound of y */
8753  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8754  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8755  }
8756  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8757  {
8758  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8759  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8760  }
8761  else
8762  {
8763  SCIPerrorMessage("scalar is zero in aggregation\n");
8764  return SCIP_INVALIDDATA;
8765  }
8766  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8767  childnewleft, childnewright, added) );
8768  break;
8769 
8771  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8772  return SCIP_INVALIDDATA;
8773 
8774  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8775  assert(var->negatedvar != NULL);
8777  assert(var->negatedvar->negatedvar == var);
8778 
8779  childnewright = -left + var->data.negate.constant;
8780  childnewleft = -right + var->data.negate.constant;
8781 
8782  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8783  childnewleft, childnewright, added) );
8784  break;
8785 
8786  default:
8787  SCIPerrorMessage("unknown variable status\n");
8788  return SCIP_INVALIDDATA;
8789  }
8790 
8791  return SCIP_OKAY;
8792 }
8793 
8794 /** performs the current add of domain, changes all parents accordingly */
8795 static
8797  SCIP_VAR* var, /**< problem variable */
8798  BMS_BLKMEM* blkmem, /**< block memory */
8799  SCIP_SET* set, /**< global SCIP settings */
8800  SCIP_STAT* stat, /**< problem statistics */
8801  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8802  SCIP_Real left, /**< left bound of open interval in new hole */
8803  SCIP_Real right, /**< right bound of open interval in new hole */
8804  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8805  )
8806 {
8807  SCIP_VAR* parentvar;
8808  SCIP_Real newlb;
8809  SCIP_Real newub;
8810  int i;
8811 
8812  assert(var != NULL);
8813  assert(added != NULL);
8814  assert(blkmem != NULL);
8815 
8816  /* the interval should not be empty */
8817  assert(SCIPsetIsLT(set, left, right));
8818 
8819  /* the the interval bound should already be adjusted */
8820  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8821  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8822 
8823  /* the the interval should lay between the lower and upper bound */
8824  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8825  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8826 
8827  /* add hole to hole list */
8828  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8829 
8830  /* check if the hole is redundant */
8831  if( !(*added) )
8832  return SCIP_OKAY;
8833 
8834  /* current bounds */
8835  newlb = var->locdom.lb;
8836  newub = var->locdom.ub;
8837 
8838  /* merge domain holes */
8839  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8840 
8841  /* the bound should not be changed */
8842  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8843  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8844 
8845 #if 0
8846  /* issue bound change event */
8847  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8848  if( var->eventfilter != NULL )
8849  {
8850  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8851  }
8852 #endif
8853 
8854  /* process parent variables */
8855  for( i = 0; i < var->nparentvars; ++i )
8856  {
8857  SCIP_Real parentnewleft;
8858  SCIP_Real parentnewright;
8859  SCIP_Bool localadded;
8860 
8861  parentvar = var->parentvars[i];
8862  assert(parentvar != NULL);
8863 
8864  switch( SCIPvarGetStatus(parentvar) )
8865  {
8867  parentnewleft = left;
8868  parentnewright = right;
8869  break;
8870 
8871  case SCIP_VARSTATUS_COLUMN:
8872  case SCIP_VARSTATUS_LOOSE:
8873  case SCIP_VARSTATUS_FIXED:
8875  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8876  return SCIP_INVALIDDATA;
8877 
8878  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8879  assert(parentvar->data.aggregate.var == var);
8880 
8881  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8882  {
8883  /* a > 0 -> change upper bound of x */
8884  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8885  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8886  }
8887  else
8888  {
8889  /* a < 0 -> change lower bound of x */
8890  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8891 
8892  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8893  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8894  }
8895  break;
8896 
8897  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8898  assert(parentvar->negatedvar != NULL);
8899  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8900  assert(parentvar->negatedvar->negatedvar == parentvar);
8901 
8902  parentnewright = -left + parentvar->data.negate.constant;
8903  parentnewleft = -right + parentvar->data.negate.constant;
8904  break;
8905 
8906  default:
8907  SCIPerrorMessage("unknown variable status\n");
8908  return SCIP_INVALIDDATA;
8909  }
8910 
8911  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8912 
8913  /* perform hole added for parent variable */
8914  assert(blkmem != NULL);
8915  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8916  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8917  parentnewleft, parentnewright, &localadded) );
8918  assert(localadded);
8919  }
8920 
8921  return SCIP_OKAY;
8922 }
8923 
8924 /** adds a hole to the variable's current local domain */
8926  SCIP_VAR* var, /**< problem variable */
8927  BMS_BLKMEM* blkmem, /**< block memory */
8928  SCIP_SET* set, /**< global SCIP settings */
8929  SCIP_STAT* stat, /**< problem statistics */
8930  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8931  SCIP_Real left, /**< left bound of open interval in new hole */
8932  SCIP_Real right, /**< right bound of open interval in new hole */
8933  SCIP_Bool* added /**< pointer to store whether the hole was added */
8934  )
8935 {
8936  SCIP_Real childnewleft;
8937  SCIP_Real childnewright;
8938 
8939  assert(var != NULL);
8940 
8941  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8942 
8943  assert(set != NULL);
8944  assert(var->scip == set->scip);
8945  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8946  assert(blkmem != NULL);
8947  assert(added != NULL);
8948 
8949  /* the interval should not be empty */
8950  assert(SCIPsetIsLT(set, left, right));
8951 
8952  /* the the interval bound should already be adjusted */
8953  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8954  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8955 
8956  /* the the interval should lay between the lower and upper bound */
8957  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8958  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8959 
8960  /* change bounds of attached variables */
8961  switch( SCIPvarGetStatus(var) )
8962  {
8964  if( var->data.original.transvar != NULL )
8965  {
8966  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8967  left, right, added) );
8968  }
8969  else
8970  {
8971  assert(set->stage == SCIP_STAGE_PROBLEM);
8972  SCIPstatIncrement(stat, set, domchgcount);
8973  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8974  }
8975  break;
8976 
8977  case SCIP_VARSTATUS_COLUMN:
8978  case SCIP_VARSTATUS_LOOSE:
8979  SCIPstatIncrement(stat, set, domchgcount);
8980  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8981  break;
8982 
8983  case SCIP_VARSTATUS_FIXED:
8984  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8985  return SCIP_INVALIDDATA;
8986 
8987  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8988  assert(var->data.aggregate.var != NULL);
8989 
8990  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8991  {
8992  /* a > 0 -> change lower bound of y */
8993  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8994  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8995  }
8996  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8997  {
8998  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8999  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9000  }
9001  else
9002  {
9003  SCIPerrorMessage("scalar is zero in aggregation\n");
9004  return SCIP_INVALIDDATA;
9005  }
9006  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9007  childnewleft, childnewright, added) );
9008  break;
9009 
9011  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9012  return SCIP_INVALIDDATA;
9013 
9014  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9015  assert(var->negatedvar != NULL);
9017  assert(var->negatedvar->negatedvar == var);
9018 
9019  childnewright = -left + var->data.negate.constant;
9020  childnewleft = -right + var->data.negate.constant;
9021 
9022  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9023  break;
9024 
9025  default:
9026  SCIPerrorMessage("unknown variable status\n");
9027  return SCIP_INVALIDDATA;
9028  }
9029 
9030  return SCIP_OKAY;
9031 }
9032 
9033 /** resets the global and local bounds of original variable to their original values */
9035  SCIP_VAR* var, /**< problem variable */
9036  BMS_BLKMEM* blkmem, /**< block memory */
9037  SCIP_SET* set, /**< global SCIP settings */
9038  SCIP_STAT* stat /**< problem statistics */
9039  )
9040 {
9041  assert(var != NULL);
9042  assert(set != NULL);
9043  assert(var->scip == set->scip);
9044  assert(SCIPvarIsOriginal(var));
9045  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9046  * the transformed variable has been fixed */
9047  assert(SCIPvarGetTransVar(var) == NULL);
9048 
9049  /* copy the original bounds back to the global and local bounds */
9050  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9051  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9052  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9053  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9054 
9055  /* free the global and local holelists and duplicate the original ones */
9056  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9057  holelistFree(&var->glbdom.holelist, blkmem);
9058  holelistFree(&var->locdom.holelist, blkmem);
9059  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9060  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9061 
9062  return SCIP_OKAY;
9063 }
9064 
9065 /** issues a IMPLADDED event on the given variable */
9066 static
9068  SCIP_VAR* var, /**< problem variable to change */
9069  BMS_BLKMEM* blkmem, /**< block memory */
9070  SCIP_SET* set, /**< global SCIP settings */
9071  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9072  )
9073 {
9074  SCIP_EVENT* event;
9075 
9076  assert(var != NULL);
9077 
9078  /* issue IMPLADDED event on variable */
9079  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9080  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9081 
9082  return SCIP_OKAY;
9083 }
9084 
9085 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9086 static
9088  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9089  BMS_BLKMEM* blkmem, /**< block memory */
9090  SCIP_SET* set, /**< global SCIP settings */
9091  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9092  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9093  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9094  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9095  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9096  )
9097 {
9098  SCIP_Bool added;
9099 
9100  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9101  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9102  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9103  *
9104  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9105  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9106  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9107  * variable bound can be ignored.
9108  *
9109  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9110  * equivalence of the variables should be checked here.
9111  */
9112  if( var == vbvar )
9113  {
9114  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9115  * can be checked via the global bounds of the variable */
9116 #ifndef NDEBUG
9117  SCIP_Real lb;
9118  SCIP_Real ub;
9119 
9120  lb = SCIPvarGetLbGlobal(var);
9121  ub = SCIPvarGetUbGlobal(var);
9122 
9123  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9124  {
9125  if( vbcoef > 0.0 )
9126  {
9127  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9128  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9129  }
9130  else
9131  {
9132  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9133  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9134  }
9135  }
9136  else
9137  {
9138  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9139  if( vbcoef > 0.0 )
9140  {
9141  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9142  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9143  }
9144  else
9145  {
9146  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9147  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9148  }
9149  }
9150 #endif
9151  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9152  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9153 
9154  return SCIP_OKAY;
9155  }
9156 
9157  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9158  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9159 
9160  /* check variable bound on debugging solution */
9161  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9162 
9163  /* perform the addition */
9164  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9165  {
9166  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9167  }
9168  else
9169  {
9170  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9171  }
9172  var->closestvblpcount = -1;
9173 
9174  if( added )
9175  {
9176  /* issue IMPLADDED event */
9177  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9178  }
9179 
9180  return SCIP_OKAY;
9181 }
9182 
9183 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9184 static
9185 void checkImplic(
9186  SCIP_SET* set, /**< global SCIP settings */
9187  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9188  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9189  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9190  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9191  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9192  )
9193 {
9194  SCIP_Real impllb;
9195  SCIP_Real implub;
9196 
9197  assert(redundant != NULL);
9198  assert(infeasible != NULL);
9199 
9200  impllb = SCIPvarGetLbGlobal(implvar);
9201  implub = SCIPvarGetUbGlobal(implvar);
9202  if( impltype == SCIP_BOUNDTYPE_LOWER )
9203  {
9204  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9205  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9206  }
9207  else
9208  {
9209  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9210  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9211  }
9212 }
9213 
9214 /** applies the given implication, if it is not redundant */
9215 static
9217  BMS_BLKMEM* blkmem, /**< block memory */
9218  SCIP_SET* set, /**< global SCIP settings */
9219  SCIP_STAT* stat, /**< problem statistics */
9220  SCIP_PROB* transprob, /**< transformed problem */
9221  SCIP_PROB* origprob, /**< original problem */
9222  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9223  SCIP_REOPT* reopt, /**< reoptimization data structure */
9224  SCIP_LP* lp, /**< current LP data */
9225  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9226  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9227  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9228  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9229  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9230  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9231  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9232  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9233  )
9234 {
9235  SCIP_Real implub;
9236  SCIP_Real impllb;
9237 
9238  assert(infeasible != NULL);
9239 
9240  *infeasible = FALSE;
9241 
9242  implub = SCIPvarGetUbGlobal(implvar);
9243  impllb = SCIPvarGetLbGlobal(implvar);
9244  if( impltype == SCIP_BOUNDTYPE_LOWER )
9245  {
9246  if( SCIPsetIsFeasGT(set, implbound, implub) )
9247  {
9248  /* the implication produces a conflict: the problem is infeasible */
9249  *infeasible = TRUE;
9250  }
9251  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9252  {
9253  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9254  * with the local bound, in this case we need to store the bound change as pending bound change
9255  */
9256  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9257  {
9258  assert(tree != NULL);
9259  assert(transprob != NULL);
9260  assert(SCIPprobIsTransformed(transprob));
9261 
9262  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9263  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9264  }
9265  else
9266  {
9267  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9268  }
9269 
9270  if( nbdchgs != NULL )
9271  (*nbdchgs)++;
9272  }
9273  }
9274  else
9275  {
9276  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9277  {
9278  /* the implication produces a conflict: the problem is infeasible */
9279  *infeasible = TRUE;
9280  }
9281  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9282  {
9283  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9284  * with the local bound, in this case we need to store the bound change as pending bound change
9285  */
9286  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9287  {
9288  assert(tree != NULL);
9289  assert(transprob != NULL);
9290  assert(SCIPprobIsTransformed(transprob));
9291 
9292  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9293  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9294  }
9295  else
9296  {
9297  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9298  }
9299 
9300  if( nbdchgs != NULL )
9301  (*nbdchgs)++;
9302  }
9303  }
9304 
9305  return SCIP_OKAY;
9306 }
9307 
9308 /** actually performs the addition of an implication to the variable's implication arrays,
9309  * and adds the corresponding implication or variable bound to the implied variable;
9310  * if the implication is conflicting, the variable is fixed to the opposite value;
9311  * if the variable is already fixed to the given value, the implication is performed immediately;
9312  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9313  */
9314 static
9316  SCIP_VAR* var, /**< problem variable */
9317  BMS_BLKMEM* blkmem, /**< block memory */
9318  SCIP_SET* set, /**< global SCIP settings */
9319  SCIP_STAT* stat, /**< problem statistics */
9320  SCIP_PROB* transprob, /**< transformed problem */
9321  SCIP_PROB* origprob, /**< original problem */
9322  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9323  SCIP_REOPT* reopt, /**< reoptimization data structure */
9324  SCIP_LP* lp, /**< current LP data */
9325  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9326  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9327  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9328  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9329  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9330  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9331  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9332  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9333  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9334  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9335  SCIP_Bool* added /**< pointer to store whether an implication was added */
9336  )
9337 {
9338  SCIP_Bool redundant;
9339  SCIP_Bool conflict;
9340 
9341  assert(var != NULL);
9342  assert(SCIPvarIsActive(var));
9344  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9345  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9346  assert(infeasible != NULL);
9347  assert(added != NULL);
9348 
9349  /* check implication on debugging solution */
9350  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9351 
9352  *infeasible = FALSE;
9353  *added = FALSE;
9354 
9355  /* check, if the implication is redundant or infeasible */
9356  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9357  assert(!redundant || !conflict);
9358  if( redundant )
9359  return SCIP_OKAY;
9360 
9361  if( var == implvar )
9362  {
9363  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9364  * x == varfixing => x < 0 or x > 1
9365  */
9366  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9367  conflict = TRUE;
9368  else
9369  {
9370  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9371  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9372  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9373  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9374  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9375  if( !conflict )
9376  return SCIP_OKAY;
9377  }
9378  }
9379 
9380  /* check, if the variable is already fixed */
9381  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9382  {
9383  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9384  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9385  {
9386  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9387  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9388  }
9389  return SCIP_OKAY;
9390  }
9391 
9392  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9393  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9394 
9395  if( !conflict )
9396  {
9397  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9398 
9399  if( SCIPvarIsBinary(implvar) )
9400  {
9401  SCIP_VAR* vars[2];
9402  SCIP_Bool vals[2];
9403 
9404  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9405  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9406 
9407  vars[0] = var;
9408  vars[1] = implvar;
9409  vals[0] = varfixing;
9410  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9411 
9412  /* add the clique to the clique table */
9413  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9414  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9415 
9416  if( !conflict )
9417  return SCIP_OKAY;
9418  }
9419  else
9420  {
9421  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9422  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9423  SCIPvarGetName(var), varfixing,
9424  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9425  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9426  isshortcut, &conflict, added) );
9427  }
9428  }
9429  assert(!conflict || !(*added));
9430 
9431  /* on conflict, fix the variable to the opposite value */
9432  if( conflict )
9433  {
9434  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9435 
9436  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9437  * with the local bound, in this case we need to store the bound change as pending bound change
9438  */
9439  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9440  {
9441  assert(tree != NULL);
9442  assert(transprob != NULL);
9443  assert(SCIPprobIsTransformed(transprob));
9444 
9445  if( varfixing )
9446  {
9447  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9448  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9449  }
9450  else
9451  {
9452  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9453  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9454  }
9455  }
9456  else
9457  {
9458  if( varfixing )
9459  {
9460  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9461  }
9462  else
9463  {
9464  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9465  }
9466  }
9467  if( nbdchgs != NULL )
9468  (*nbdchgs)++;
9469 
9470  return SCIP_OKAY;
9471  }
9472  else if( *added )
9473  {
9474  /* issue IMPLADDED event */
9475  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9476  }
9477  else
9478  {
9479  /* the implication was redundant: the inverse is also redundant */
9480  return SCIP_OKAY;
9481  }
9482 
9483  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9484 
9485  /* check, whether implied variable is binary */
9486  if( !SCIPvarIsBinary(implvar) )
9487  {
9488  SCIP_Real lb;
9489  SCIP_Real ub;
9490 
9491  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9492  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9493  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9494  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9495  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9496  * for numerical reasons, ignore variable bounds with large absolute coefficient
9497  */
9498  lb = SCIPvarGetLbGlobal(implvar);
9499  ub = SCIPvarGetUbGlobal(implvar);
9500  if( impltype == SCIP_BOUNDTYPE_UPPER )
9501  {
9502  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9503  {
9504  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9505  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9506  }
9507  }
9508  else
9509  {
9510  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9511  {
9512  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9513  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9514  }
9515  }
9516  }
9517 
9518  return SCIP_OKAY;
9519 }
9520 
9521 /** adds transitive closure for binary implication x = a -> y = b */
9522 static
9524  SCIP_VAR* var, /**< problem variable */
9525  BMS_BLKMEM* blkmem, /**< block memory */
9526  SCIP_SET* set, /**< global SCIP settings */
9527  SCIP_STAT* stat, /**< problem statistics */
9528  SCIP_PROB* transprob, /**< transformed problem */
9529  SCIP_PROB* origprob, /**< original problem */
9530  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9531  SCIP_REOPT* reopt, /**< reoptimization data structure */
9532  SCIP_LP* lp, /**< current LP data */
9533  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9534  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9535  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9536  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9537  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9538  SCIP_Bool implvarfixing, /**< fixing b in implication */
9539  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9540  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9541  )
9542 {
9543  SCIP_VAR** implvars;
9544  SCIP_BOUNDTYPE* impltypes;
9545  SCIP_Real* implbounds;
9546  int nimpls;
9547  int i;
9548 
9549  *infeasible = FALSE;
9550 
9551  /* binary variable: implications of implvar */
9552  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9553  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9554  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9555  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9556 
9557  /* if variable has too many implications, the implication graph may become too dense */
9558  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9559 
9560  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9561  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9562  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9563  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9564  * only thing that can happen is that we add the same implication twice - this does no harm
9565  */
9566  while ( i >= 0 && !(*infeasible) )
9567  {
9568  SCIP_Bool added;
9569 
9570  assert(implvars[i] != implvar);
9571 
9572  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9573  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9574  */
9575  if( SCIPvarIsActive(implvars[i]) )
9576  {
9577  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9578  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9579  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9580  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9581  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9582  }
9583  --i;
9584  }
9585 
9586  return SCIP_OKAY;
9587 }
9588 
9589 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9590  * implication to the variable's implication list;
9591  * if the implication is conflicting, the variable is fixed to the opposite value;
9592  * if the variable is already fixed to the given value, the implication is performed immediately;
9593  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9594  */
9595 static
9597  SCIP_VAR* var, /**< problem variable */
9598  BMS_BLKMEM* blkmem, /**< block memory */
9599  SCIP_SET* set, /**< global SCIP settings */
9600  SCIP_STAT* stat, /**< problem statistics */
9601  SCIP_PROB* transprob, /**< transformed problem */
9602  SCIP_PROB* origprob, /**< original problem */
9603  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9604  SCIP_REOPT* reopt, /**< reoptimization data structure */
9605  SCIP_LP* lp, /**< current LP data */
9606  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9607  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9608  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9609  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9610  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9611  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9612  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9613  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9614  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9615  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9616  )
9617 {
9618  SCIP_Bool added;
9619 
9620  assert(var != NULL);
9621  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9622  assert(SCIPvarIsActive(var));
9623  assert(implvar != NULL);
9624  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9625  assert(infeasible != NULL);
9626 
9627  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9628  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9629  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9630 
9631  if( *infeasible || var == implvar || !transitive || !added )
9632  return SCIP_OKAY;
9633 
9634  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9635 
9636  /* add transitive closure */
9637  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9638  {
9639  SCIP_Bool implvarfixing;
9640 
9641  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9642 
9643  /* binary variable: implications of implvar */
9644  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9645  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9646 
9647  /* inverse implication */
9648  if( !(*infeasible) )
9649  {
9650  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9651  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9652  }
9653  }
9654  else
9655  {
9656  /* non-binary variable: variable lower bounds of implvar */
9657  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9658  {
9659  SCIP_VAR** vlbvars;
9660  SCIP_Real* vlbcoefs;
9661  SCIP_Real* vlbconstants;
9662  int nvlbvars;
9663  int i;
9664 
9665  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9666  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9667  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9668  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9669 
9670  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9671  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9672  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9673  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9674  * is that we add the same implication twice - this does no harm
9675  */
9676  i = nvlbvars-1;
9677  while ( i >= 0 && !(*infeasible) )
9678  {
9679  assert(vlbvars[i] != implvar);
9680  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9681 
9682  /* we have x == varfixing -> y <= b and y >= c*z + d:
9683  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9684  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9685  *
9686  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9687  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9688  * aggregation variable (the one which will stay active);
9689  *
9690  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9691  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9692  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9693  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9694  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9695  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9696  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9697  * have to explicitly check that the active variable has not a variable status
9698  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9699  */
9700  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9701  {
9702  SCIP_Real vbimplbound;
9703 
9704  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9705  if( vlbcoefs[i] >= 0.0 )
9706  {
9707  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9708  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9709  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9710  infeasible, nbdchgs, &added) );
9711  }
9712  else
9713  {
9714  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9715  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9716  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9717  infeasible, nbdchgs, &added) );
9718  }
9719  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9720  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9721  }
9722  --i;
9723  }
9724  }
9725 
9726  /* non-binary variable: variable upper bounds of implvar */
9727  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9728  {
9729  SCIP_VAR** vubvars;
9730  SCIP_Real* vubcoefs;
9731  SCIP_Real* vubconstants;
9732  int nvubvars;
9733  int i;
9734 
9735  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9736  vubvars = SCIPvboundsGetVars(implvar->vubs);
9737  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9738  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9739 
9740  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9741  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9742  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9743  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9744  * is that we add the same implication twice - this does no harm
9745  */
9746  i = nvubvars-1;
9747  while ( i >= 0 && !(*infeasible) )
9748  {
9749  assert(vubvars[i] != implvar);
9750  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9751 
9752  /* we have x == varfixing -> y >= b and y <= c*z + d:
9753  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9754  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9755  *
9756  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9757  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9758  * aggregation variable (the one which will stay active);
9759  *
9760  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9761  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9762  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9763  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9764  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9765  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9766  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9767  * have to explicitly check that the active variable has not a variable status
9768  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9769  */
9770  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9771  {
9772  SCIP_Real vbimplbound;
9773 
9774  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9775  if( vubcoefs[i] >= 0.0 )
9776  {
9777  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9778  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9779  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9780  infeasible, nbdchgs, &added) );
9781  }
9782  else
9783  {
9784  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9785  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9786  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9787  infeasible, nbdchgs, &added) );
9788  }
9789  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9790  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9791  }
9792  --i;
9793  }
9794  }
9795  }
9796 
9797  return SCIP_OKAY;
9798 }
9799 
9800 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9801  * if z is binary, the corresponding valid implication for z is also added;
9802  * improves the global bounds of the variable and the vlb variable if possible
9803  */
9805  SCIP_VAR* var, /**< problem variable */
9806  BMS_BLKMEM* blkmem, /**< block memory */
9807  SCIP_SET* set, /**< global SCIP settings */
9808  SCIP_STAT* stat, /**< problem statistics */
9809  SCIP_PROB* transprob, /**< transformed problem */
9810  SCIP_PROB* origprob, /**< original problem */
9811  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9812  SCIP_REOPT* reopt, /**< reoptimization data structure */
9813  SCIP_LP* lp, /**< current LP data */
9814  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9815  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9816  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9817  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9818  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9819  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9820  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9821  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9822  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9823  )
9824 {
9825  assert(var != NULL);
9826  assert(set != NULL);
9827  assert(var->scip == set->scip);
9828  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9829  assert(infeasible != NULL);
9830 
9831  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9832 
9833  *infeasible = FALSE;
9834  if( nbdchgs != NULL )
9835  *nbdchgs = 0;
9836 
9837  switch( SCIPvarGetStatus(var) )
9838  {
9840  assert(var->data.original.transvar != NULL);
9841  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9842  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9843  break;
9844 
9845  case SCIP_VARSTATUS_COLUMN:
9846  case SCIP_VARSTATUS_LOOSE:
9847  case SCIP_VARSTATUS_FIXED:
9848  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9849  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9850  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9851 
9852  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9853  if( SCIPsetIsZero(set, vlbcoef) )
9854  {
9855  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9856  *infeasible = TRUE;
9857  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9858  {
9859  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9860  * with the local bound, in this case we need to store the bound change as pending bound change
9861  */
9862  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9863  {
9864  assert(tree != NULL);
9865  assert(transprob != NULL);
9866  assert(SCIPprobIsTransformed(transprob));
9867 
9868  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9869  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9870  }
9871  else
9872  {
9873  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9874  }
9875 
9876  if( nbdchgs != NULL )
9877  (*nbdchgs)++;
9878  }
9879  }
9880  else if( var == vlbvar )
9881  {
9882  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
9883  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
9884  {
9885  if( SCIPsetIsPositive(set, vlbconstant) )
9886  *infeasible = TRUE;
9887  return SCIP_OKAY;
9888  }
9889  else
9890  {
9891  SCIP_Real lb = SCIPvarGetLbGlobal(var);
9892  SCIP_Real ub = SCIPvarGetUbGlobal(var);
9893 
9894  /* the variable bound constraint defines a new upper bound */
9895  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
9896  {
9897  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
9898 
9899  if( SCIPsetIsFeasLT(set, newub, lb) )
9900  {
9901  *infeasible = TRUE;
9902  return SCIP_OKAY;
9903  }
9904  else if( SCIPsetIsFeasLT(set, newub, ub) )
9905  {
9906  /* bound might be adjusted due to integrality condition */
9907  newub = adjustedUb(set, SCIPvarGetType(var), newub);
9908 
9909  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9910  * with the local bound, in this case we need to store the bound change as pending bound change
9911  */
9912  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9913  {
9914  assert(tree != NULL);
9915  assert(transprob != NULL);
9916  assert(SCIPprobIsTransformed(transprob));
9917 
9918  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9919  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9920  }
9921  else
9922  {
9923  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
9924  }
9925 
9926  if( nbdchgs != NULL )
9927  (*nbdchgs)++;
9928  }
9929  }
9930  /* the variable bound constraint defines a new lower bound */
9931  else
9932  {
9933  SCIP_Real newlb;
9934 
9935  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
9936 
9937  newlb = vlbconstant / (1.0 - vlbcoef);
9938 
9939  if( SCIPsetIsFeasGT(set, newlb, ub) )
9940  {
9941  *infeasible = TRUE;
9942  return SCIP_OKAY;
9943  }
9944  else if( SCIPsetIsFeasGT(set, newlb, lb) )
9945  {
9946  /* bound might be adjusted due to integrality condition */
9947  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
9948 
9949  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9950  * with the local bound, in this case we need to store the bound change as pending bound change
9951  */
9952  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9953  {
9954  assert(tree != NULL);
9955  assert(transprob != NULL);
9956  assert(SCIPprobIsTransformed(transprob));
9957 
9958  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9959  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9960  }
9961  else
9962  {
9963  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
9964  }
9965 
9966  if( nbdchgs != NULL )
9967  (*nbdchgs)++;
9968  }
9969  }
9970  }
9971  }
9972  else if( SCIPvarIsActive(vlbvar) )
9973  {
9974  SCIP_Real xlb;
9975  SCIP_Real xub;
9976  SCIP_Real zlb;
9977  SCIP_Real zub;
9978  SCIP_Real minvlb;
9979  SCIP_Real maxvlb;
9980 
9982  assert(vlbcoef != 0.0);
9983 
9984  minvlb = -SCIPsetInfinity(set);
9985  maxvlb = SCIPsetInfinity(set);
9986 
9987  xlb = SCIPvarGetLbGlobal(var);
9988  xub = SCIPvarGetUbGlobal(var);
9989  zlb = SCIPvarGetLbGlobal(vlbvar);
9990  zub = SCIPvarGetUbGlobal(vlbvar);
9991 
9992  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9993  if( vlbcoef >= 0.0 )
9994  {
9995  SCIP_Real newzub;
9996 
9997  if( !SCIPsetIsInfinity(set, xub) )
9998  {
9999  /* x >= b*z + d -> z <= (x-d)/b */
10000  newzub = (xub - vlbconstant)/vlbcoef;
10001 
10002  /* return if the new bound is less than -infinity */
10003  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10004  return SCIP_OKAY;
10005 
10006  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10007  {
10008  *infeasible = TRUE;
10009  return SCIP_OKAY;
10010  }
10011  if( SCIPsetIsFeasLT(set, newzub, zub) )
10012  {
10013  /* bound might be adjusted due to integrality condition */
10014  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10015 
10016  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10017  * with the local bound, in this case we need to store the bound change as pending bound change
10018  */
10019  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10020  {
10021  assert(tree != NULL);
10022  assert(transprob != NULL);
10023  assert(SCIPprobIsTransformed(transprob));
10024 
10025  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10026  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10027  }
10028  else
10029  {
10030  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10031  }
10032  zub = newzub;
10033 
10034  if( nbdchgs != NULL )
10035  (*nbdchgs)++;
10036  }
10037  maxvlb = vlbcoef * zub + vlbconstant;
10038  if( !SCIPsetIsInfinity(set, -zlb) )
10039  minvlb = vlbcoef * zlb + vlbconstant;
10040  }
10041  else
10042  {
10043  if( !SCIPsetIsInfinity(set, zub) )
10044  maxvlb = vlbcoef * zub + vlbconstant;
10045  if( !SCIPsetIsInfinity(set, -zlb) )
10046  minvlb = vlbcoef * zlb + vlbconstant;
10047  }
10048  }
10049  else
10050  {
10051  SCIP_Real newzlb;
10052 
10053  if( !SCIPsetIsInfinity(set, xub) )
10054  {
10055  /* x >= b*z + d -> z >= (x-d)/b */
10056  newzlb = (xub - vlbconstant)/vlbcoef;
10057 
10058  /* return if the new bound is larger than infinity */
10059  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10060  return SCIP_OKAY;
10061 
10062  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10063  {
10064  *infeasible = TRUE;
10065  return SCIP_OKAY;
10066  }
10067  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10068  {
10069  /* bound might be adjusted due to integrality condition */
10070  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10071 
10072  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10073  * with the local bound, in this case we need to store the bound change as pending bound change
10074  */
10075  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10076  {
10077  assert(tree != NULL);
10078  assert(transprob != NULL);
10079  assert(SCIPprobIsTransformed(transprob));
10080 
10081  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10082  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10083  }
10084  else
10085  {
10086  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10087  }
10088  zlb = newzlb;
10089 
10090  if( nbdchgs != NULL )
10091  (*nbdchgs)++;
10092  }
10093  maxvlb = vlbcoef * zlb + vlbconstant;
10094  if( !SCIPsetIsInfinity(set, zub) )
10095  minvlb = vlbcoef * zub + vlbconstant;
10096  }
10097  else
10098  {
10099  if( !SCIPsetIsInfinity(set, -zlb) )
10100  maxvlb = vlbcoef * zlb + vlbconstant;
10101  if( !SCIPsetIsInfinity(set, zub) )
10102  minvlb = vlbcoef * zub + vlbconstant;
10103  }
10104  }
10105  if( maxvlb < minvlb )
10106  maxvlb = minvlb;
10107 
10108  /* adjust bounds due to integrality of variable */
10109  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10110  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10111 
10112  /* check bounds for feasibility */
10113  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10114  {
10115  *infeasible = TRUE;
10116  return SCIP_OKAY;
10117  }
10118  /* improve global lower bound of variable */
10119  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10120  {
10121  /* bound might be adjusted due to integrality condition */
10122  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10123 
10124  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10125  * with the local bound, in this case we need to store the bound change as pending bound change
10126  */
10127  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10128  {
10129  assert(tree != NULL);
10130  assert(transprob != NULL);
10131  assert(SCIPprobIsTransformed(transprob));
10132 
10133  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10134  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10135  }
10136  else
10137  {
10138  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10139  }
10140  xlb = minvlb;
10141 
10142  if( nbdchgs != NULL )
10143  (*nbdchgs)++;
10144  }
10145  minvlb = xlb;
10146 
10147  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10148  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10149  {
10150  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10151  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10152  */
10153 
10154  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10155 
10156  if( vlbcoef >= 0.0 )
10157  {
10158  vlbcoef = maxvlb - minvlb;
10159  vlbconstant = minvlb;
10160  }
10161  else
10162  {
10163  vlbcoef = minvlb - maxvlb;
10164  vlbconstant = maxvlb;
10165  }
10166  }
10167 
10168  /* add variable bound to the variable bounds list */
10169  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10170  {
10171  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10172  assert(!SCIPsetIsZero(set, vlbcoef));
10173 
10174  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10175  * list, thereby also adding the variable bound (or implication) to the other variable
10176  */
10177  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10178  {
10179  /* add corresponding implication:
10180  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10181  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10182  */
10183  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10184  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10185  infeasible, nbdchgs) );
10186  }
10187  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10188  {
10189  /* add corresponding implication:
10190  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10191  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10192  */
10193  SCIP_Real implbound;
10194  implbound = -vlbconstant/vlbcoef;
10195 
10196  /* tighten the implication bound if the variable is integer */
10197  if( SCIPvarIsIntegral(vlbvar) )
10198  {
10199  if( vlbcoef >= 0 )
10200  implbound = SCIPsetFloor(set, implbound);
10201  else
10202  implbound = SCIPsetCeil(set, implbound);
10203  }
10204  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10205  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10206  implbound, transitive, infeasible, nbdchgs) );
10207  }
10208  else
10209  {
10210  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10211  }
10212  }
10213  }
10214  break;
10215 
10217  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10218  * y <= b/a * z + (d-c)/a, if a < 0
10219  */
10220  assert(var->data.aggregate.var != NULL);
10221  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10222  {
10223  /* a > 0 -> add variable lower bound */
10224  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10225  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10226  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10227  }
10228  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10229  {
10230  /* a < 0 -> add variable upper bound */
10231  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10232  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10233  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10234  }
10235  else
10236  {
10237  SCIPerrorMessage("scalar is zero in aggregation\n");
10238  return SCIP_INVALIDDATA;
10239  }
10240  break;
10241 
10243  /* nothing to do here */
10244  break;
10245 
10247  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10248  assert(var->negatedvar != NULL);
10250  assert(var->negatedvar->negatedvar == var);
10251  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10252  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10253  nbdchgs) );
10254  break;
10255 
10256  default:
10257  SCIPerrorMessage("unknown variable status\n");
10258  return SCIP_INVALIDDATA;
10259  }
10260 
10261  return SCIP_OKAY;
10262 }
10263 
10264 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10265  * if z is binary, the corresponding valid implication for z is also added;
10266  * updates the global bounds of the variable and the vub variable correspondingly
10267  */
10269  SCIP_VAR* var, /**< problem variable */
10270  BMS_BLKMEM* blkmem, /**< block memory */
10271  SCIP_SET* set, /**< global SCIP settings */
10272  SCIP_STAT* stat, /**< problem statistics */
10273  SCIP_PROB* transprob, /**< transformed problem */
10274  SCIP_PROB* origprob, /**< original problem */
10275  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10276  SCIP_REOPT* reopt, /**< reoptimization data structure */
10277  SCIP_LP* lp, /**< current LP data */
10278  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10279  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10280  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10281  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10282  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10283  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10284  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10285  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10286  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10287  )
10288 {
10289  assert(var != NULL);
10290  assert(set != NULL);
10291  assert(var->scip == set->scip);
10292  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10293  assert(infeasible != NULL);
10294 
10295  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10296 
10297  *infeasible = FALSE;
10298  if( nbdchgs != NULL )
10299  *nbdchgs = 0;
10300 
10301  switch( SCIPvarGetStatus(var) )
10302  {
10304  assert(var->data.original.transvar != NULL);
10305  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10306  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10307  break;
10308 
10309  case SCIP_VARSTATUS_COLUMN:
10310  case SCIP_VARSTATUS_LOOSE:
10311  case SCIP_VARSTATUS_FIXED:
10312  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10313  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10314  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10315  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10316 
10317  /* if the vub coefficient is zero, just update the upper bound of the variable */
10318  if( SCIPsetIsZero(set, vubcoef) )
10319  {
10320  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10321  *infeasible = TRUE;
10322  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10323  {
10324  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10325  * with the local bound, in this case we need to store the bound change as pending bound change
10326  */
10327  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10328  {
10329  assert(tree != NULL);
10330  assert(transprob != NULL);
10331  assert(SCIPprobIsTransformed(transprob));
10332 
10333  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10334  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10335  }
10336  else
10337  {
10338  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10339  }
10340 
10341  if( nbdchgs != NULL )
10342  (*nbdchgs)++;
10343  }
10344  }
10345  else if( var == vubvar )
10346  {
10347  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10348  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10349  {
10350  if( SCIPsetIsNegative(set, vubconstant) )
10351  *infeasible = TRUE;
10352  return SCIP_OKAY;
10353  }
10354  else
10355  {
10356  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10357  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10358 
10359  /* the variable bound constraint defines a new lower bound */
10360  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10361  {
10362  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10363 
10364  if( SCIPsetIsFeasGT(set, newlb, ub) )
10365  {
10366  *infeasible = TRUE;
10367  return SCIP_OKAY;
10368  }
10369  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10370  {
10371  /* bound might be adjusted due to integrality condition */
10372  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10373 
10374  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10375  * with the local bound, in this case we need to store the bound change as pending bound change
10376  */
10377  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10378  {
10379  assert(tree != NULL);
10380  assert(transprob != NULL);
10381  assert(SCIPprobIsTransformed(transprob));
10382 
10383  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10384  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10385  }
10386  else
10387  {
10388  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10389  }
10390 
10391  if( nbdchgs != NULL )
10392  (*nbdchgs)++;
10393  }
10394  }
10395  /* the variable bound constraint defines a new upper bound */
10396  else
10397  {
10398  SCIP_Real newub;
10399 
10400  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10401 
10402  newub = vubconstant / (1.0 - vubcoef);
10403 
10404  if( SCIPsetIsFeasLT(set, newub, lb) )
10405  {
10406  *infeasible = TRUE;
10407  return SCIP_OKAY;
10408  }
10409  else if( SCIPsetIsFeasLT(set, newub, ub) )
10410  {
10411  /* bound might be adjusted due to integrality condition */
10412  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10413 
10414  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10415  * with the local bound, in this case we need to store the bound change as pending bound change
10416  */
10417  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10418  {
10419  assert(tree != NULL);
10420  assert(transprob != NULL);
10421  assert(SCIPprobIsTransformed(transprob));
10422 
10423  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10424  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10425  }
10426  else
10427  {
10428  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10429  }
10430 
10431  if( nbdchgs != NULL )
10432  (*nbdchgs)++;
10433  }
10434  }
10435  }
10436  }
10437  else if( SCIPvarIsActive(vubvar) )
10438  {
10439  SCIP_Real xlb;
10440  SCIP_Real xub;
10441  SCIP_Real zlb;
10442  SCIP_Real zub;
10443  SCIP_Real minvub;
10444  SCIP_Real maxvub;
10445 
10447  assert(vubcoef != 0.0);
10448 
10449  minvub = -SCIPsetInfinity(set);
10450  maxvub = SCIPsetInfinity(set);
10451 
10452  xlb = SCIPvarGetLbGlobal(var);
10453  xub = SCIPvarGetUbGlobal(var);
10454  zlb = SCIPvarGetLbGlobal(vubvar);
10455  zub = SCIPvarGetUbGlobal(vubvar);
10456 
10457  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10458  if( vubcoef >= 0.0 )
10459  {
10460  SCIP_Real newzlb;
10461 
10462  if( !SCIPsetIsInfinity(set, -xlb) )
10463  {
10464  /* x <= b*z + d -> z >= (x-d)/b */
10465  newzlb = (xlb - vubconstant)/vubcoef;
10466  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10467  {
10468  *infeasible = TRUE;
10469  return SCIP_OKAY;
10470  }
10471  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10472  {
10473  /* bound might be adjusted due to integrality condition */
10474  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10475 
10476  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10477  * with the local bound, in this case we need to store the bound change as pending bound change
10478  */
10479  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10480  {
10481  assert(tree != NULL);
10482  assert(transprob != NULL);
10483  assert(SCIPprobIsTransformed(transprob));
10484 
10485  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10486  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10487  }
10488  else
10489  {
10490  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10491  }
10492  zlb = newzlb;
10493 
10494  if( nbdchgs != NULL )
10495  (*nbdchgs)++;
10496  }
10497  minvub = vubcoef * zlb + vubconstant;
10498  if( !SCIPsetIsInfinity(set, zub) )
10499  maxvub = vubcoef * zub + vubconstant;
10500  }
10501  else
10502  {
10503  if( !SCIPsetIsInfinity(set, zub) )
10504  maxvub = vubcoef * zub + vubconstant;
10505  if( !SCIPsetIsInfinity(set, -zlb) )
10506  minvub = vubcoef * zlb + vubconstant;
10507  }
10508  }
10509  else
10510  {
10511  SCIP_Real newzub;
10512 
10513  if( !SCIPsetIsInfinity(set, -xlb) )
10514  {
10515  /* x <= b*z + d -> z <= (x-d)/b */
10516  newzub = (xlb - vubconstant)/vubcoef;
10517  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10518  {
10519  *infeasible = TRUE;
10520  return SCIP_OKAY;
10521  }
10522  if( SCIPsetIsFeasLT(set, newzub, zub) )
10523  {
10524  /* bound might be adjusted due to integrality condition */
10525  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10526 
10527  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10528  * with the local bound, in this case we need to store the bound change as pending bound change
10529  */
10530  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10531  {
10532  assert(tree != NULL);
10533  assert(transprob != NULL);
10534  assert(SCIPprobIsTransformed(transprob));
10535 
10536  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10537  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10538  }
10539  else
10540  {
10541  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10542  }
10543  zub = newzub;
10544 
10545  if( nbdchgs != NULL )
10546  (*nbdchgs)++;
10547  }
10548  minvub = vubcoef * zub + vubconstant;
10549  if( !SCIPsetIsInfinity(set, -zlb) )
10550  maxvub = vubcoef * zlb + vubconstant;
10551  }
10552  else
10553  {
10554  if( !SCIPsetIsInfinity(set, zub) )
10555  minvub = vubcoef * zub + vubconstant;
10556  if( !SCIPsetIsInfinity(set, -zlb) )
10557  maxvub = vubcoef * zlb + vubconstant;
10558  }
10559  }
10560  if( minvub > maxvub )
10561  minvub = maxvub;
10562 
10563  /* adjust bounds due to integrality of vub variable */
10564  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10565  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10566 
10567  /* check bounds for feasibility */
10568  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10569  {
10570  *infeasible = TRUE;
10571  return SCIP_OKAY;
10572  }
10573 
10574  /* improve global upper bound of variable */
10575  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10576  {
10577  /* bound might be adjusted due to integrality condition */
10578  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10579 
10580  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10581  * with the local bound, in this case we need to store the bound change as pending bound change
10582  */
10583  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10584  {
10585  assert(tree != NULL);
10586  assert(transprob != NULL);
10587  assert(SCIPprobIsTransformed(transprob));
10588 
10589  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10590  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10591  }
10592  else
10593  {
10594  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10595  }
10596  xub = maxvub;
10597 
10598  if( nbdchgs != NULL )
10599  (*nbdchgs)++;
10600  }
10601  maxvub = xub;
10602 
10603  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10604  if( SCIPvarIsBinary(vubvar) )
10605  {
10606  /* b > 0: x <= (maxvub - minvub) * z + minvub
10607  * b < 0: x <= (minvub - maxvub) * z + maxvub
10608  */
10609 
10610  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10611 
10612  if( vubcoef >= 0.0 )
10613  {
10614  vubcoef = maxvub - minvub;
10615  vubconstant = minvub;
10616  }
10617  else
10618  {
10619  vubcoef = minvub - maxvub;
10620  vubconstant = maxvub;
10621  }
10622  }
10623 
10624  /* add variable bound to the variable bounds list */
10625  if( SCIPsetIsFeasLT(set, minvub, xub) )
10626  {
10627  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10628  assert(!SCIPsetIsZero(set, vubcoef));
10629 
10630  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10631  * list, thereby also adding the variable bound (or implication) to the other variable
10632  */
10633  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10634  {
10635  /* add corresponding implication:
10636  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10637  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10638  */
10639  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10640  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10641  infeasible, nbdchgs) );
10642  }
10643  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10644  {
10645  /* add corresponding implication:
10646  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10647  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10648  */
10649  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10650  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10651  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10652  }
10653  else
10654  {
10655  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10656  }
10657  }
10658  }
10659  break;
10660 
10662  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10663  * y >= b/a * z + (d-c)/a, if a < 0
10664  */
10665  assert(var->data.aggregate.var != NULL);
10666  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10667  {
10668  /* a > 0 -> add variable upper bound */
10669  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10670  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10671  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10672  }
10673  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10674  {
10675  /* a < 0 -> add variable lower bound */
10676  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10677  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10678  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10679  }
10680  else
10681  {
10682  SCIPerrorMessage("scalar is zero in aggregation\n");
10683  return SCIP_INVALIDDATA;
10684  }
10685  break;
10686 
10688  /* nothing to do here */
10689  break;
10690 
10692  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10693  assert(var->negatedvar != NULL);
10695  assert(var->negatedvar->negatedvar == var);
10696  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10697  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10698  nbdchgs) );
10699  break;
10700 
10701  default:
10702  SCIPerrorMessage("unknown variable status\n");
10703  return SCIP_INVALIDDATA;
10704  }
10705 
10706  return SCIP_OKAY;
10707 }
10708 
10709 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10710  * also adds the corresponding implication or variable bound to the implied variable;
10711  * if the implication is conflicting, the variable is fixed to the opposite value;
10712  * if the variable is already fixed to the given value, the implication is performed immediately;
10713  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10714  */
10716  SCIP_VAR* var, /**< problem variable */
10717  BMS_BLKMEM* blkmem, /**< block memory */
10718  SCIP_SET* set, /**< global SCIP settings */
10719  SCIP_STAT* stat, /**< problem statistics */
10720  SCIP_PROB* transprob, /**< transformed problem */
10721  SCIP_PROB* origprob, /**< original problem */
10722  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10723  SCIP_REOPT* reopt, /**< reoptimization data structure */
10724  SCIP_LP* lp, /**< current LP data */
10725  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10726  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10727  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10728  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10729  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10730  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10731  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10732  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10733  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10734  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10735  )
10736 {
10737  assert(var != NULL);
10738  assert(set != NULL);
10739  assert(var->scip == set->scip);
10740  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10741  assert(infeasible != NULL);
10742 
10743  *infeasible = FALSE;
10744  if( nbdchgs != NULL )
10745  *nbdchgs = 0;
10746 
10747  switch( SCIPvarGetStatus(var) )
10748  {
10750  assert(var->data.original.transvar != NULL);
10751  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10752  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10753  nbdchgs) );
10754  break;
10755 
10756  case SCIP_VARSTATUS_COLUMN:
10757  case SCIP_VARSTATUS_LOOSE:
10758  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10759  * the variable, the implication can be applied directly;
10760  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10761  */
10762  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10763  {
10764  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10765  {
10766  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10767  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10768  }
10769  }
10770  else
10771  {
10772  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10773  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10774  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10775  {
10776  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10777  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10778  }
10779  }
10780  break;
10781 
10782  case SCIP_VARSTATUS_FIXED:
10783  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10784  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10785  {
10786  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10787  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10788  }
10789  break;
10790 
10792  /* implication added for x == 1:
10793  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10794  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10795  * implication added for x == 0:
10796  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10797  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10798  *
10799  * use only binary variables z
10800  */
10801  assert(var->data.aggregate.var != NULL);
10802  if( SCIPvarIsBinary(var->data.aggregate.var) )
10803  {
10804  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10805  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10806 
10807  if( var->data.aggregate.scalar > 0 )
10808  {
10809  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10810  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10811  nbdchgs) );
10812  }
10813  else
10814  {
10815  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10816  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10817  nbdchgs) );
10818  }
10819  }
10820  break;
10821 
10823  /* nothing to do here */
10824  break;
10825 
10827  /* implication added for x == 1:
10828  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10829  * implication added for x == 0:
10830  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10831  */
10832  assert(var->negatedvar != NULL);
10834  assert(var->negatedvar->negatedvar == var);
10835  assert(SCIPvarIsBinary(var->negatedvar));
10836 
10838  {
10839  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10840  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10841  }
10842  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10843  else
10844  {
10845  /* if the implied variable is of binary type exchange the variables */
10846  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10847  {
10848  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10849  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10850  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10851  infeasible, nbdchgs) );
10852  }
10853  else
10854  {
10855  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10856  * implication as variable bounds
10857  */
10858 
10859  /* add variable lower bound on the negation of var */
10860  if( varfixing )
10861  {
10862  /* (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
10863  * as variable lower bound
10864  */
10865  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10866  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10867  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10868  }
10869  else
10870  {
10871  /* (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
10872  * as variable upper bound
10873  */
10874  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10875  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10876  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10877  }
10878 
10879  /* add variable bound on implvar */
10880  if( impltype == SCIP_BOUNDTYPE_UPPER )
10881  {
10882  /* (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
10883  * as variable upper bound
10884  */
10885  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10886  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10887  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10888  }
10889  else
10890  {
10891  /* (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
10892  * as variable upper bound
10893  */
10894  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10895  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10896  transitive, infeasible, nbdchgs) );
10897  }
10898  }
10899  }
10900  break;
10901 
10902  default:
10903  SCIPerrorMessage("unknown variable status\n");
10904  return SCIP_INVALIDDATA;
10905  }
10906 
10907  return SCIP_OKAY;
10908 }
10909 
10910 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10911  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10912  * both variables must be active, variable x must be binary
10913  */
10915  SCIP_VAR* var, /**< problem variable x */
10916  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10917  SCIP_VAR* implvar, /**< variable y to search for */
10918  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10919  )
10920 {
10921  assert(var != NULL);
10922  assert(implvar != NULL);
10923  assert(SCIPvarIsActive(var));
10924  assert(SCIPvarIsActive(implvar));
10925  assert(SCIPvarIsBinary(var));
10926 
10927  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10928 }
10929 
10930 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10931  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10932  * both variables must be active binary variables
10933  */
10935  SCIP_VAR* var, /**< problem variable x */
10936  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10937  SCIP_VAR* implvar, /**< variable y to search for */
10938  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10939  )
10940 {
10941  assert(SCIPvarIsBinary(implvar));
10942 
10943  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10944 }
10945 
10946 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10948  SCIP_VAR* var, /**< problem variable */
10949  BMS_BLKMEM* blkmem, /**< block memory */
10950  SCIP_SET* set, /**< global SCIP settings */
10951  SCIP_STAT* stat, /**< problem statistics */
10952  SCIP_PROB* transprob, /**< transformed problem */
10953  SCIP_PROB* origprob, /**< original problem */
10954  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10955  SCIP_REOPT* reopt, /**< reoptimization data structure */
10956  SCIP_LP* lp, /**< current LP data */
10957  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10958  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10959  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10960  SCIP_Bool value, /**< value to fix variable to */
10961  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10962  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10963  )
10964 {
10965  assert(var != NULL);
10966  assert(set != NULL);
10967  assert(var->scip == set->scip);
10968  assert(infeasible != NULL);
10969 
10970  *infeasible = FALSE;
10971 
10972  if( value == FALSE )
10973  {
10974  if( var->glbdom.lb > 0.5 )
10975  *infeasible = TRUE;
10976  else if( var->glbdom.ub > 0.5 )
10977  {
10978  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10979  * with the local bound, in this case we need to store the bound change as pending bound change
10980  */
10981  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10982  {
10983  assert(tree != NULL);
10984  assert(transprob != NULL);
10985  assert(SCIPprobIsTransformed(transprob));
10986 
10987  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10988  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10989  }
10990  else
10991  {
10992  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10993  }
10994 
10995  if( nbdchgs != NULL )
10996  (*nbdchgs)++;
10997  }
10998  }
10999  else
11000  {
11001  if( var->glbdom.ub < 0.5 )
11002  *infeasible = TRUE;
11003  else if( var->glbdom.lb < 0.5 )
11004  {
11005  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11006  * with the local bound, in this case we need to store the bound change as pending bound change
11007  */
11008  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11009  {
11010  assert(tree != NULL);
11011  assert(transprob != NULL);
11012  assert(SCIPprobIsTransformed(transprob));
11013 
11014  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11015  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11016  }
11017  else
11018  {
11019  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11020  }
11021 
11022  if( nbdchgs != NULL )
11023  (*nbdchgs)++;
11024  }
11025  }
11026 
11027  /* during presolving, the variable should have been removed immediately from all its cliques */
11028  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11029 
11030  return SCIP_OKAY;
11031 }
11032 
11033 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11034  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11035  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11036  * the opposite of the value they take in the clique
11037  */
11039  SCIP_VAR* var, /**< problem variable */
11040  BMS_BLKMEM* blkmem, /**< block memory */
11041  SCIP_SET* set, /**< global SCIP settings */
11042  SCIP_STAT* stat, /**< problem statistics */
11043  SCIP_PROB* transprob, /**< transformed problem */
11044  SCIP_PROB* origprob, /**< original problem */
11045  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11046  SCIP_REOPT* reopt, /**< reoptimization data structure */
11047  SCIP_LP* lp, /**< current LP data */
11048  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11049  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11050  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11051  SCIP_Bool value, /**< value of the variable in the clique */
11052  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11053  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11054  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11055  )
11056 {
11057  assert(var != NULL);
11058  assert(set != NULL);
11059  assert(var->scip == set->scip);
11060  assert(SCIPvarIsBinary(var));
11061  assert(infeasible != NULL);
11062 
11063  *infeasible = FALSE;
11064 
11065  /* get corresponding active problem variable */
11066  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11071  assert(SCIPvarIsBinary(var));
11072 
11073  /* only column and loose variables may be member of a clique */
11075  {
11076  SCIP_Bool doubleentry;
11077  SCIP_Bool oppositeentry;
11078 
11079  /* add variable to clique */
11080  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11081 
11082  /* add clique to variable's clique list */
11083  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11084 
11085  /* check consistency of cliquelist */
11086  SCIPcliquelistCheck(var->cliquelist, var);
11087 
11088  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11089  if( doubleentry )
11090  {
11091  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11092  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11093  }
11094 
11095  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11096  * to the opposite of the value they take in the clique
11097  */
11098  if( oppositeentry )
11099  {
11100  SCIP_VAR** vars;
11101  SCIP_Bool* values;
11102  int nvars;
11103  int i;
11104 
11105  nvars = SCIPcliqueGetNVars(clique);
11106  vars = SCIPcliqueGetVars(clique);
11107  values = SCIPcliqueGetValues(clique);
11108  for( i = 0; i < nvars && !(*infeasible); ++i )
11109  {
11110  if( vars[i] == var )
11111  continue;
11112 
11113  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11114  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11115  }
11116  }
11117  }
11118 
11119  return SCIP_OKAY;
11120 }
11121 
11122 /** adds a filled clique to the cliquelists of all corresponding variables */
11124  SCIP_VAR** vars, /**< problem variables */
11125  SCIP_Bool* values, /**< values of the variables in the clique */
11126  int nvars, /**< number of problem variables */
11127  BMS_BLKMEM* blkmem, /**< block memory */
11128  SCIP_SET* set, /**< global SCIP settings */
11129  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11130  )
11131 {
11132  SCIP_VAR* var;
11133  int v;
11134 
11135  assert(vars != NULL);
11136  assert(values != NULL);
11137  assert(nvars > 0);
11138  assert(set != NULL);
11139  assert(blkmem != NULL);
11140  assert(clique != NULL);
11141 
11142  for( v = nvars - 1; v >= 0; --v )
11143  {
11144  var = vars[v];
11145  assert(SCIPvarIsBinary(var));
11147 
11148  /* add clique to variable's clique list */
11149  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11150 
11151  /* check consistency of cliquelist */
11152  SCIPcliquelistCheck(var->cliquelist, var);
11153  }
11154 
11155  return SCIP_OKAY;
11156 }
11157 
11158 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11159  * itself
11160  */
11162  SCIP_VAR* var, /**< problem variable */
11163  BMS_BLKMEM* blkmem, /**< block memory */
11164  SCIP_SET* set, /**< global SCIP settings */
11165  SCIP_Bool value, /**< value of the variable in the clique */
11166  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11167  )
11168 {
11169  assert(var != NULL);
11170  assert(SCIPvarIsBinary(var));
11172 
11173  /* add clique to variable's clique list */
11174  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11175 
11176  return SCIP_OKAY;
11177 }
11178 
11179 
11180 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11181  * itself
11182  */
11184  SCIP_VAR* var, /**< problem variable */
11185  BMS_BLKMEM* blkmem, /**< block memory */
11186  SCIP_Bool value, /**< value of the variable in the clique */
11187  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11188  )
11189 {
11190  assert(var != NULL);
11191  assert(SCIPvarIsBinary(var));
11192 
11193  /* delete clique from variable's clique list */
11194  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11195 
11196  return SCIP_OKAY;
11197 }
11198 
11199 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11201  SCIP_VAR* var, /**< problem variable */
11202  BMS_BLKMEM* blkmem, /**< block memory */
11203  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11204  SCIP_Bool value, /**< value of the variable in the clique */
11205  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11206  )
11207 {
11208  assert(var != NULL);
11209  assert(SCIPvarIsBinary(var));
11210 
11211  /* get corresponding active problem variable */
11212  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11217  assert(SCIPvarIsBinary(var));
11218 
11219  /* only column and loose variables may be member of a clique */
11221  {
11222  /* delete clique from variable's clique list */
11223  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11224 
11225  /* delete variable from clique */
11226  SCIPcliqueDelVar(clique, cliquetable, var, value);
11227 
11228  /* check consistency of cliquelist */
11229  SCIPcliquelistCheck(var->cliquelist, var);
11230  }
11231 
11232  return SCIP_OKAY;
11233 }
11234 
11235 /** returns whether there is a clique that contains both given variable/value pairs;
11236  * the variables must be active binary variables;
11237  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11238  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11239  *
11240  * @note a variable with it's negated variable are NOT! in a clique
11241  * @note a variable with itself are in a clique
11242  */
11244  SCIP_VAR* var1, /**< first variable */
11245  SCIP_Bool value1, /**< value of first variable */
11246  SCIP_VAR* var2, /**< second variable */
11247  SCIP_Bool value2, /**< value of second variable */
11248  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11249  )
11250 {
11251  assert(var1 != NULL);
11252  assert(var2 != NULL);
11253  assert(SCIPvarIsActive(var1));
11254  assert(SCIPvarIsActive(var2));
11255  assert(SCIPvarIsBinary(var1));
11256  assert(SCIPvarIsBinary(var2));
11257 
11258  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11259  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11260 }
11261 
11262 /** actually changes the branch factor of the variable and of all parent variables */
11263 static
11265  SCIP_VAR* var, /**< problem variable */
11266  SCIP_SET* set, /**< global SCIP settings */
11267  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11268  )
11269 {
11270  SCIP_VAR* parentvar;
11271  SCIP_Real eps;
11272  int i;
11273 
11274  assert(var != NULL);
11275  assert(set != NULL);
11276  assert(var->scip == set->scip);
11277 
11278  /* only use positive values */
11279  eps = SCIPsetEpsilon(set);
11280  branchfactor = MAX(branchfactor, eps);
11281 
11282  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11283 
11284  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11285  return SCIP_OKAY;
11286 
11287  /* change the branch factor */
11288  var->branchfactor = branchfactor;
11289 
11290  /* process parent variables */
11291  for( i = 0; i < var->nparentvars; ++i )
11292  {
11293  parentvar = var->parentvars[i];
11294  assert(parentvar != NULL);
11295 
11296  switch( SCIPvarGetStatus(parentvar) )
11297  {
11299  /* do not change priorities across the border between transformed and original problem */
11300  break;
11301 
11302  case SCIP_VARSTATUS_COLUMN:
11303  case SCIP_VARSTATUS_LOOSE:
11304  case SCIP_VARSTATUS_FIXED:
11306  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11307  SCIPABORT();
11308  return SCIP_INVALIDDATA; /*lint !e527*/
11309 
11312  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11313  break;
11314 
11315  default:
11316  SCIPerrorMessage("unknown variable status\n");
11317  SCIPABORT();
11318  return SCIP_ERROR; /*lint !e527*/
11319  }
11320  }
11321 
11322  return SCIP_OKAY;
11323 }
11324 
11325 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11326  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11327  */
11329  SCIP_VAR* var, /**< problem variable */
11330  SCIP_SET* set, /**< global SCIP settings */
11331  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11332  )
11333 {
11334  int v;
11335 
11336  assert(var != NULL);
11337  assert(set != NULL);
11338  assert(var->scip == set->scip);
11339  assert(branchfactor >= 0.0);
11340 
11341  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11342 
11343  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11344  return SCIP_OKAY;
11345 
11346  /* change priorities of attached variables */
11347  switch( SCIPvarGetStatus(var) )
11348  {
11350  if( var->data.original.transvar != NULL )
11351  {
11352  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11353  }
11354  else
11355  {
11356  assert(set->stage == SCIP_STAGE_PROBLEM);
11357  var->branchfactor = branchfactor;
11358  }
11359  break;
11360 
11361  case SCIP_VARSTATUS_COLUMN:
11362  case SCIP_VARSTATUS_LOOSE:
11363  case SCIP_VARSTATUS_FIXED:
11364  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11365  break;
11366 
11368  assert(var->data.aggregate.var != NULL);
11369  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11370  break;
11371 
11373  assert(!var->donotmultaggr);
11374  for( v = 0; v < var->data.multaggr.nvars; ++v )
11375  {
11376  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11377  }
11378  break;
11379 
11381  assert(var->negatedvar != NULL);
11383  assert(var->negatedvar->negatedvar == var);
11384  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11385  break;
11386 
11387  default:
11388  SCIPerrorMessage("unknown variable status\n");
11389  SCIPABORT();
11390  return SCIP_ERROR; /*lint !e527*/
11391  }
11392 
11393  return SCIP_OKAY;
11394 }
11395 
11396 /** actually changes the branch priority of the variable and of all parent variables */
11397 static
11399  SCIP_VAR* var, /**< problem variable */
11400  int branchpriority /**< branching priority of the variable */
11401  )
11402 {
11403  SCIP_VAR* parentvar;
11404  int i;
11405 
11406  assert(var != NULL);
11407 
11408  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11409  var->name, var->branchpriority, branchpriority);
11410 
11411  if( branchpriority == var->branchpriority )
11412  return SCIP_OKAY;
11413 
11414  /* change the branch priority */
11415  var->branchpriority = branchpriority;
11416 
11417  /* process parent variables */
11418  for( i = 0; i < var->nparentvars; ++i )
11419  {
11420  parentvar = var->parentvars[i];
11421  assert(parentvar != NULL);
11422 
11423  switch( SCIPvarGetStatus(parentvar) )
11424  {
11426  /* do not change priorities across the border between transformed and original problem */
11427  break;
11428 
11429  case SCIP_VARSTATUS_COLUMN:
11430  case SCIP_VARSTATUS_LOOSE:
11431  case SCIP_VARSTATUS_FIXED:
11433  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11434  SCIPABORT();
11435  return SCIP_INVALIDDATA; /*lint !e527*/
11436 
11439  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11440  break;
11441 
11442  default:
11443  SCIPerrorMessage("unknown variable status\n");
11444  return SCIP_ERROR;
11445  }
11446  }
11447 
11448  return SCIP_OKAY;
11449 }
11450 
11451 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11452  * with lower priority in selection of branching variable
11453  */
11455  SCIP_VAR* var, /**< problem variable */
11456  int branchpriority /**< branching priority of the variable */
11457  )
11458 {
11459  int v;
11460 
11461  assert(var != NULL);
11462 
11463  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11464 
11465  if( var->branchpriority == branchpriority )
11466  return SCIP_OKAY;
11467 
11468  /* change priorities of attached variables */
11469  switch( SCIPvarGetStatus(var) )
11470  {
11472  if( var->data.original.transvar != NULL )
11473  {
11474  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11475  }
11476  else
11477  var->branchpriority = branchpriority;
11478  break;
11479 
11480  case SCIP_VARSTATUS_COLUMN:
11481  case SCIP_VARSTATUS_LOOSE:
11482  case SCIP_VARSTATUS_FIXED:
11483  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11484  break;
11485 
11487  assert(var->data.aggregate.var != NULL);
11488  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11489  break;
11490 
11492  assert(!var->donotmultaggr);
11493  for( v = 0; v < var->data.multaggr.nvars; ++v )
11494  {
11495  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11496  }
11497  break;
11498 
11500  assert(var->negatedvar != NULL);
11502  assert(var->negatedvar->negatedvar == var);
11503  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11504  break;
11505 
11506  default:
11507  SCIPerrorMessage("unknown variable status\n");
11508  SCIPABORT();
11509  return SCIP_ERROR; /*lint !e527*/
11510  }
11511 
11512  return SCIP_OKAY;
11513 }
11514 
11515 /** actually changes the branch direction of the variable and of all parent variables */
11516 static
11518  SCIP_VAR* var, /**< problem variable */
11519  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11520  )
11521 {
11522  SCIP_VAR* parentvar;
11523  int i;
11524 
11525  assert(var != NULL);
11526 
11527  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11528  var->name, var->branchdirection, branchdirection);
11529 
11530  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11531  return SCIP_OKAY;
11532 
11533  /* change the branch direction */
11534  var->branchdirection = branchdirection; /*lint !e641*/
11535 
11536  /* process parent variables */
11537  for( i = 0; i < var->nparentvars; ++i )
11538  {
11539  parentvar = var->parentvars[i];
11540  assert(parentvar != NULL);
11541 
11542  switch( SCIPvarGetStatus(parentvar) )
11543  {
11545  /* do not change directions across the border between transformed and original problem */
11546  break;
11547 
11548  case SCIP_VARSTATUS_COLUMN:
11549  case SCIP_VARSTATUS_LOOSE:
11550  case SCIP_VARSTATUS_FIXED:
11552  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11553  SCIPABORT();
11554  return SCIP_INVALIDDATA; /*lint !e527*/
11555 
11557  if( parentvar->data.aggregate.scalar > 0.0 )
11558  {
11559  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11560  }
11561  else
11562  {
11563  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11564  }
11565  break;
11566 
11568  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11569  break;
11570 
11571  default:
11572  SCIPerrorMessage("unknown variable status\n");
11573  SCIPABORT();
11574  return SCIP_ERROR; /*lint !e527*/
11575  }
11576  }
11577 
11578  return SCIP_OKAY;
11579 }
11580 
11581 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11582  * with lower direction in selection of branching variable
11583  */
11585  SCIP_VAR* var, /**< problem variable */
11586  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11587  )
11588 {
11589  int v;
11590 
11591  assert(var != NULL);
11592 
11593  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11594 
11595  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11596  return SCIP_OKAY;
11597 
11598  /* change directions of attached variables */
11599  switch( SCIPvarGetStatus(var) )
11600  {
11602  if( var->data.original.transvar != NULL )
11603  {
11604  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11605  }
11606  else
11607  var->branchdirection = branchdirection; /*lint !e641*/
11608  break;
11609 
11610  case SCIP_VARSTATUS_COLUMN:
11611  case SCIP_VARSTATUS_LOOSE:
11612  case SCIP_VARSTATUS_FIXED:
11613  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11614  break;
11615 
11617  assert(var->data.aggregate.var != NULL);
11618  if( var->data.aggregate.scalar > 0.0 )
11619  {
11620  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11621  }
11622  else
11623  {
11625  }
11626  break;
11627 
11629  assert(!var->donotmultaggr);
11630  for( v = 0; v < var->data.multaggr.nvars; ++v )
11631  {
11632  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11633  assert(var->data.multaggr.vars[v] != NULL);
11635  {
11636  if( var->data.multaggr.scalars[v] > 0.0 )
11637  {
11638  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11639  }
11640  else
11641  {
11643  }
11644  }
11645  }
11646  break;
11647 
11649  assert(var->negatedvar != NULL);
11651  assert(var->negatedvar->negatedvar == var);
11653  break;
11654 
11655  default:
11656  SCIPerrorMessage("unknown variable status\n");
11657  SCIPABORT();
11658  return SCIP_ERROR; /*lint !e527*/
11659  }
11660 
11661  return SCIP_OKAY;
11662 }
11663 
11664 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11665  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11666  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11667  * are equal, which means both variables are equal
11668  */
11670  SCIP_VAR* var1, /**< first problem variable */
11671  SCIP_VAR* var2 /**< second problem variable */
11672  )
11673 {
11674  assert(var1 != NULL);
11675  assert(var2 != NULL);
11678 
11680  var1 = SCIPvarGetNegatedVar(var1);
11682  var2 = SCIPvarGetNegatedVar(var2);
11683 
11684  assert(var1 != NULL);
11685  assert(var2 != NULL);
11686 
11687  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11688  return -1;
11689  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11690  return +1;
11691 
11692  assert(var1 == var2);
11693  return 0;
11694 }
11695 
11696 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11697  * variables are handled as the same variables
11698  */
11699 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11701  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11702 }
11703 
11704 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11705  * variable index; returns 0 if both indices are equal, which means both variables are equal
11706  */
11707 int SCIPvarCompare(
11708  SCIP_VAR* var1, /**< first problem variable */
11709  SCIP_VAR* var2 /**< second problem variable */
11710  )
11711 {
11712  assert(var1 != NULL);
11713  assert(var2 != NULL);
11714 
11715  if( var1->index < var2->index )
11716  return -1;
11717  else if( var1->index > var2->index )
11718  return +1;
11719  else
11720  {
11721  assert(var1 == var2);
11722  return 0;
11723  }
11724 }
11725 
11726 /** comparison method for sorting variables by non-decreasing index */
11727 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11729  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11730 }
11731 
11732 /** comparison method for sorting variables by non-decreasing objective coefficient */
11733 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11735  SCIP_Real obj1;
11736  SCIP_Real obj2;
11737 
11738  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11739  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11740 
11741  if( obj1 < obj2 )
11742  return -1;
11743  else if( obj1 > obj2 )
11744  return +1;
11745  else
11746  return 0;
11747 }
11748 
11749 /** hash key retrieval function for variables */
11750 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11751 { /*lint --e{715}*/
11752  return elem;
11753 }
11754 
11755 /** returns TRUE iff the indices of both variables are equal */
11756 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11757 { /*lint --e{715}*/
11758  if( key1 == key2 )
11759  return TRUE;
11760  return FALSE;
11761 }
11762 
11763 /** returns the hash value of the key */
11764 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11765 { /*lint --e{715}*/
11766  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11767  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11768 }
11769 
11770 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11772  SCIP_SET* set, /**< global SCIP settings */
11773  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11774  * variables, if enough slots exist
11775  */
11776  int* nvars, /**< number of given variables, and as output number of active variables,
11777  * if enough slots exist
11778  */
11779  int varssize, /**< available slots in vars array */
11780  int* requiredsize /**< pointer to store the required array size for the active variables */
11781  )
11782 {
11783  SCIP_VAR** activevars;
11784  int nactivevars;
11785  int activevarssize;
11786 
11787  SCIP_VAR* var;
11788  int v;
11789 
11790  SCIP_VAR** tmpvars;
11791  SCIP_VAR** multvars;
11792  int tmpvarssize;
11793  int ntmpvars;
11794  int noldtmpvars;
11795  int nmultvars;
11796 
11797  assert(set != NULL);
11798  assert(nvars != NULL);
11799  assert(vars != NULL || *nvars == 0);
11800  assert(varssize >= *nvars);
11801  assert(requiredsize != NULL);
11802 
11803  *requiredsize = 0;
11804 
11805  if( *nvars == 0 )
11806  return SCIP_OKAY;
11807 
11808  nactivevars = 0;
11809  activevarssize = *nvars;
11810  ntmpvars = *nvars;
11811  tmpvarssize = *nvars;
11812 
11813  /* temporary memory */
11814  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11815  /* coverity[copy_paste_error] */
11816  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11817 
11818  noldtmpvars = ntmpvars;
11819 
11820  /* sort all variables to combine equal variables easily */
11821  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11822  for( v = ntmpvars - 1; v > 0; --v )
11823  {
11824  /* combine same variables */
11825  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11826  {
11827  --ntmpvars;
11828  tmpvars[v] = tmpvars[ntmpvars];
11829  }
11830  }
11831  /* sort all variables again to combine equal variables later on */
11832  if( noldtmpvars > ntmpvars )
11833  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11834 
11835  /* collect for each variable the representation in active variables */
11836  while( ntmpvars >= 1 )
11837  {
11838  --ntmpvars;
11839  var = tmpvars[ntmpvars];
11840  assert( var != NULL );
11841 
11842  switch( SCIPvarGetStatus(var) )
11843  {
11845  if( var->data.original.transvar == NULL )
11846  {
11847  SCIPerrorMessage("original variable has no transformed variable attached\n");
11848  SCIPABORT();
11849  return SCIP_INVALIDDATA; /*lint !e527*/
11850  }
11851  tmpvars[ntmpvars] = var->data.original.transvar;
11852  ++ntmpvars;
11853  break;
11854 
11856  tmpvars[ntmpvars] = var->data.aggregate.var;
11857  ++ntmpvars;
11858  break;
11859 
11861  tmpvars[ntmpvars] = var->negatedvar;
11862  ++ntmpvars;
11863  break;
11864 
11865  case SCIP_VARSTATUS_LOOSE:
11866  case SCIP_VARSTATUS_COLUMN:
11867  /* check for space in temporary memory */
11868  if( nactivevars >= activevarssize )
11869  {
11870  activevarssize *= 2;
11871  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11872  assert(nactivevars < activevarssize);
11873  }
11874  activevars[nactivevars] = var;
11875  nactivevars++;
11876  break;
11877 
11879  /* x = a_1*y_1 + ... + a_n*y_n + c */
11880  nmultvars = var->data.multaggr.nvars;
11881  multvars = var->data.multaggr.vars;
11882 
11883  /* check for space in temporary memory */
11884  if( nmultvars + ntmpvars > tmpvarssize )
11885  {
11886  while( nmultvars + ntmpvars > tmpvarssize )
11887  tmpvarssize *= 2;
11888  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11889  assert(nmultvars + ntmpvars <= tmpvarssize);
11890  }
11891 
11892  /* copy all multi-aggregation variables into our working array */
11893  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11894 
11895  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11896  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11897 
11898  ntmpvars += nmultvars;
11899  noldtmpvars = ntmpvars;
11900 
11901  /* sort all variables to combine equal variables easily */
11902  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11903  for( v = ntmpvars - 1; v > 0; --v )
11904  {
11905  /* combine same variables */
11906  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11907  {
11908  --ntmpvars;
11909  tmpvars[v] = tmpvars[ntmpvars];
11910  }
11911  }
11912  /* sort all variables again to combine equal variables later on */
11913  if( noldtmpvars > ntmpvars )
11914  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11915 
11916  break;
11917 
11918  case SCIP_VARSTATUS_FIXED:
11919  /* no need for memorizing fixed variables */
11920  break;
11921 
11922  default:
11923  SCIPerrorMessage("unknown variable status\n");
11924  SCIPABORT();
11925  return SCIP_INVALIDDATA; /*lint !e527*/
11926  }
11927  }
11928 
11929  /* sort variable array by variable index */
11930  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11931 
11932  /* eliminate duplicates and count required size */
11933  v = nactivevars - 1;
11934  while( v > 0 )
11935  {
11936  /* combine both variable since they are the same */
11937  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11938  {
11939  --nactivevars;
11940  activevars[v] = activevars[nactivevars];
11941  }
11942  --v;
11943  }
11944  *requiredsize = nactivevars;
11945 
11946  if( varssize >= *requiredsize )
11947  {
11948  assert(vars != NULL);
11949 
11950  *nvars = *requiredsize;
11951  BMScopyMemoryArray(vars, activevars, nactivevars);
11952  }
11953 
11954  SCIPsetFreeBufferArray(set, &tmpvars);
11955  SCIPsetFreeBufferArray(set, &activevars);
11956 
11957  return SCIP_OKAY;
11958 }
11959 
11960 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11961  * @note the content of the given array will/might change
11962  */
11963 void SCIPvarsGetProbvar(
11964  SCIP_VAR** vars, /**< array of problem variables */
11965  int nvars /**< number of variables */
11966  )
11967 {
11968  int v;
11969 
11970  assert(vars != NULL || nvars == 0);
11971 
11972  for( v = nvars - 1; v >= 0; --v )
11973  {
11974  assert(vars != NULL);
11975  assert(vars[v] != NULL);
11976 
11977  vars[v] = SCIPvarGetProbvar(vars[v]);
11978  assert(vars[v] != NULL);
11979  }
11980 }
11981 
11982 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11984  SCIP_VAR* var /**< problem variable */
11985  )
11986 {
11987  SCIP_VAR* retvar;
11988 
11989  assert(var != NULL);
11990 
11991  retvar = var;
11992 
11993  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11994 
11995  while( TRUE ) /*lint !e716 */
11996  {
11997  assert(retvar != NULL);
11998 
11999  switch( SCIPvarGetStatus(retvar) )
12000  {
12002  if( retvar->data.original.transvar == NULL )
12003  {
12004  SCIPerrorMessage("original variable has no transformed variable attached\n");
12005  SCIPABORT();
12006  return NULL; /*lint !e527 */
12007  }
12008  retvar = retvar->data.original.transvar;
12009  break;
12010 
12011  case SCIP_VARSTATUS_LOOSE:
12012  case SCIP_VARSTATUS_COLUMN:
12013  case SCIP_VARSTATUS_FIXED:
12014  return retvar;
12015 
12017  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12018  if ( retvar->data.multaggr.nvars == 1 )
12019  retvar = retvar->data.multaggr.vars[0];
12020  else
12021  return retvar;
12022  break;
12023 
12025  retvar = retvar->data.aggregate.var;
12026  break;
12027 
12029  retvar = retvar->negatedvar;
12030  break;
12031 
12032  default:
12033  SCIPerrorMessage("unknown variable status\n");
12034  SCIPABORT();
12035  return NULL; /*lint !e527*/
12036  }
12037  }
12038 }
12039 
12040 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12041  * negation status of each variable
12042  */
12044  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12045  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12046  int nvars /**< number of variables and values in vars and negated array */
12047  )
12048 {
12049  SCIP_VAR** var;
12050  SCIP_Bool* negated;
12051  int v;
12052 
12053  assert(vars != NULL);
12054  assert(*vars != NULL || nvars == 0);
12055  assert(negatedarr != NULL);
12056  assert(*negatedarr != NULL || nvars == 0);
12057 
12058  for( v = nvars - 1; v >= 0; --v )
12059  {
12060  var = &((*vars)[v]);
12061  negated = &((*negatedarr)[v]);
12062 
12063  /* get problem variable */
12064  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12065  }
12066 
12067  return SCIP_OKAY;
12068 }
12069 
12070 
12071 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12072  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12073  * FALSE is used)
12074  */
12076  SCIP_VAR** var, /**< pointer to binary problem variable */
12077  SCIP_Bool* negated /**< pointer to update the negation status */
12078  )
12079 {
12081 #ifndef NDEBUG
12082  SCIP_Real constant = 0.0;
12083  SCIP_Bool orignegated;
12084 #endif
12085 
12086  assert(var != NULL);
12087  assert(*var != NULL);
12088  assert(negated != NULL);
12089  assert(SCIPvarIsBinary(*var));
12090 
12091 #ifndef NDEBUG
12092  orignegated = *negated;
12093 #endif
12094 
12095  while( !active && *var != NULL )
12096  {
12097  switch( SCIPvarGetStatus(*var) )
12098  {
12100  if( (*var)->data.original.transvar == NULL )
12101  return SCIP_OKAY;
12102  *var = (*var)->data.original.transvar;
12103  break;
12104 
12105  case SCIP_VARSTATUS_LOOSE:
12106  case SCIP_VARSTATUS_COLUMN:
12107  case SCIP_VARSTATUS_FIXED:
12108  active = TRUE;
12109  break;
12110 
12112  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12113  if ( (*var)->data.multaggr.nvars == 1 )
12114  {
12115  assert( (*var)->data.multaggr.vars != NULL );
12116  assert( (*var)->data.multaggr.scalars != NULL );
12117  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12118  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12119 
12120  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12121  * another variable which needs to be fixed
12122  *
12123  * e.g. x = y - 1 => (x = 0 && y = 1)
12124  * e.g. x = y + 1 => (x = 1 && y = 0)
12125  *
12126  * is this special case we need to return the muti-aggregation
12127  */
12128  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)) )
12129  {
12130  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12131  }
12132  else
12133  {
12134  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12135  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12136  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12137  * we will return the aggregated variable;
12138  */
12139  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12140  {
12141  active = TRUE;
12142  break;
12143  }
12144 
12145  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12146  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12147  * so if this is the case, we will return the aggregated variable
12148  */
12149  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12150  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12151  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12152 
12153  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12154  {
12155  active = TRUE;
12156  break;
12157  }
12158 
12159  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12160 
12161  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12162  {
12163  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12164  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12165  * variable itself is multi-aggregated again?
12166  */
12167  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12168  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12169  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12170  }
12171  else
12172  {
12173  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12174 #ifndef NDEBUG
12175  constant += (*negated) != orignegated ? -1.0 : 1.0;
12176 #endif
12177 
12178  *negated = !(*negated);
12179  }
12180  *var = (*var)->data.multaggr.vars[0];
12181  break;
12182  }
12183  }
12184  active = TRUE;
12185  break;
12186 
12187  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12188  assert((*var)->data.aggregate.var != NULL);
12189  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12190  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12191 #ifndef NDEBUG
12192  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12193 #endif
12194 
12195  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12196  *var = (*var)->data.aggregate.var;
12197  break;
12198 
12199  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12200  assert((*var)->negatedvar != NULL);
12201 #ifndef NDEBUG
12202  constant += (*negated) != orignegated ? -1.0 : 1.0;
12203 #endif
12204 
12205  *negated = !(*negated);
12206  *var = (*var)->negatedvar;
12207  break;
12208 
12209  default:
12210  SCIPerrorMessage("unknown variable status\n");
12211  return SCIP_INVALIDDATA;
12212  }
12213  }
12214  assert(active == (*var != NULL));
12215 
12216  if( active )
12217  {
12218  assert(SCIPvarIsBinary(*var));
12219  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12220  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12221 
12222  return SCIP_OKAY;
12223  }
12224  else
12225  {
12226  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12227  return SCIP_INVALIDDATA;
12228  }
12229 }
12230 
12231 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12232  * values
12233  */
12235  SCIP_VAR** var, /**< pointer to problem variable */
12236  SCIP_Real* bound, /**< pointer to bound value to transform */
12237  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12238  )
12239 {
12240  assert(var != NULL);
12241  assert(*var != NULL);
12242  assert(bound != NULL);
12243  assert(boundtype != NULL);
12244 
12245  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12246 
12247  switch( SCIPvarGetStatus(*var) )
12248  {
12250  if( (*var)->data.original.transvar == NULL )
12251  {
12252  SCIPerrorMessage("original variable has no transformed variable attached\n");
12253  return SCIP_INVALIDDATA;
12254  }
12255  *var = (*var)->data.original.transvar;
12256  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12257  break;
12258 
12259  case SCIP_VARSTATUS_LOOSE:
12260  case SCIP_VARSTATUS_COLUMN:
12261  case SCIP_VARSTATUS_FIXED:
12262  break;
12263 
12265  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12266  if ( (*var)->data.multaggr.nvars == 1 )
12267  {
12268  assert( (*var)->data.multaggr.vars != NULL );
12269  assert( (*var)->data.multaggr.scalars != NULL );
12270  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12271 
12272  (*bound) /= (*var)->data.multaggr.scalars[0];
12273  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12274  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12275  {
12276  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12277  *boundtype = SCIP_BOUNDTYPE_UPPER;
12278  else
12279  *boundtype = SCIP_BOUNDTYPE_LOWER;
12280  }
12281  *var = (*var)->data.multaggr.vars[0];
12282  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12283  }
12284  break;
12285 
12286  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12287  assert((*var)->data.aggregate.var != NULL);
12288  assert((*var)->data.aggregate.scalar != 0.0);
12289 
12290  (*bound) /= (*var)->data.aggregate.scalar;
12291  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12292  if( (*var)->data.aggregate.scalar < 0.0 )
12293  {
12294  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12295  *boundtype = SCIP_BOUNDTYPE_UPPER;
12296  else
12297  *boundtype = SCIP_BOUNDTYPE_LOWER;
12298  }
12299  *var = (*var)->data.aggregate.var;
12300  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12301  break;
12302 
12303  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12304  assert((*var)->negatedvar != NULL);
12305  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12306  assert((*var)->negatedvar->negatedvar == *var);
12307  (*bound) = (*var)->data.negate.constant - *bound;
12308  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12309  *boundtype = SCIP_BOUNDTYPE_UPPER;
12310  else
12311  *boundtype = SCIP_BOUNDTYPE_LOWER;
12312  *var = (*var)->negatedvar;
12313  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12314  break;
12315 
12316  default:
12317  SCIPerrorMessage("unknown variable status\n");
12318  return SCIP_INVALIDDATA;
12319  }
12320 
12321  return SCIP_OKAY;
12322 }
12323 
12324 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12325  * values
12326  */
12328  SCIP_VAR** var, /**< pointer to problem variable */
12329  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12330  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12331  )
12332 {
12333  assert(var != NULL);
12334  assert(*var != NULL);
12335  assert(left != NULL);
12336  assert(right != NULL);
12337 
12338  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12339 
12340  switch( SCIPvarGetStatus(*var) )
12341  {
12343  if( (*var)->data.original.transvar == NULL )
12344  {
12345  SCIPerrorMessage("original variable has no transformed variable attached\n");
12346  return SCIP_INVALIDDATA;
12347  }
12348  *var = (*var)->data.original.transvar;
12349  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12350  break;
12351 
12352  case SCIP_VARSTATUS_LOOSE:
12353  case SCIP_VARSTATUS_COLUMN:
12354  case SCIP_VARSTATUS_FIXED:
12356  break;
12357 
12358  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12359  assert((*var)->data.aggregate.var != NULL);
12360  assert((*var)->data.aggregate.scalar != 0.0);
12361 
12362  /* scale back */
12363  (*left) /= (*var)->data.aggregate.scalar;
12364  (*right) /= (*var)->data.aggregate.scalar;
12365 
12366  /* shift back */
12367  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12368  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12369 
12370  *var = (*var)->data.aggregate.var;
12371 
12372  /* check if the interval bounds have to swapped */
12373  if( (*var)->data.aggregate.scalar < 0.0 )
12374  {
12375  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12376  }
12377  else
12378  {
12379  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12380  }
12381  break;
12382 
12383  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12384  assert((*var)->negatedvar != NULL);
12385  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12386  assert((*var)->negatedvar->negatedvar == *var);
12387 
12388  /* shift and scale back */
12389  (*left) = (*var)->data.negate.constant - (*left);
12390  (*right) = (*var)->data.negate.constant - (*right);
12391 
12392  *var = (*var)->negatedvar;
12393 
12394  /* through the negated variable the left and right interval bound have to swapped */
12395  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12396  break;
12397 
12398  default:
12399  SCIPerrorMessage("unknown variable status\n");
12400  return SCIP_INVALIDDATA;
12401  }
12402 
12403  return SCIP_OKAY;
12404 }
12405 
12406 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12407  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12408  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12409  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12410  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12411  */
12413  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12414  SCIP_SET* set, /**< global SCIP settings */
12415  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12416  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12417  )
12418 {
12419  assert(var != NULL);
12420  assert(scalar != NULL);
12421  assert(constant != NULL);
12422 
12423  while( *var != NULL )
12424  {
12425  switch( SCIPvarGetStatus(*var) )
12426  {
12428  if( (*var)->data.original.transvar == NULL )
12429  {
12430  SCIPerrorMessage("original variable has no transformed variable attached\n");
12431  return SCIP_INVALIDDATA;
12432  }
12433  *var = (*var)->data.original.transvar;
12434  break;
12435 
12436  case SCIP_VARSTATUS_LOOSE:
12437  case SCIP_VARSTATUS_COLUMN:
12438  return SCIP_OKAY;
12439 
12440  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12441  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12442  {
12443  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12444  {
12445  assert(*scalar != 0.0);
12446  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12447  (*constant) = SCIPsetInfinity(set);
12448  else
12449  (*constant) = -SCIPsetInfinity(set);
12450  }
12451  else
12452  (*constant) += *scalar * (*var)->glbdom.lb;
12453  }
12454 #ifndef NDEBUG
12455  else
12456  {
12457  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12458  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12459  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12460  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12461  }
12462 #endif
12463  *scalar = 0.0;
12464  return SCIP_OKAY;
12465 
12467  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12468  if ( (*var)->data.multaggr.nvars == 1 )
12469  {
12470  assert((*var)->data.multaggr.vars != NULL);
12471  assert((*var)->data.multaggr.scalars != NULL);
12472  assert((*var)->data.multaggr.vars[0] != NULL);
12473  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12474  {
12475  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12476  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12477  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12478  */
12479  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12480  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12481  {
12482  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12483  {
12484  assert(!SCIPsetIsInfinity(set, -(*constant)));
12485  (*constant) = SCIPsetInfinity(set);
12486  }
12487  else
12488  {
12489  assert(!SCIPsetIsInfinity(set, *constant));
12490  (*constant) = -SCIPsetInfinity(set);
12491  }
12492  (*scalar) = 0.0;
12493  }
12494  else
12495  (*constant) += *scalar * (*var)->data.multaggr.constant;
12496  }
12497  (*scalar) *= (*var)->data.multaggr.scalars[0];
12498  *var = (*var)->data.multaggr.vars[0];
12499  break;
12500  }
12501  return SCIP_OKAY;
12502 
12503  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12504  assert((*var)->data.aggregate.var != NULL);
12505  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12506  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12507  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12508  (*constant) += *scalar * (*var)->data.aggregate.constant;
12509  (*scalar) *= (*var)->data.aggregate.scalar;
12510  *var = (*var)->data.aggregate.var;
12511  break;
12512 
12513  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12514  assert((*var)->negatedvar != NULL);
12515  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12516  assert((*var)->negatedvar->negatedvar == *var);
12517  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12518  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12519  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12520  (*constant) += *scalar * (*var)->data.negate.constant;
12521  (*scalar) *= -1.0;
12522  *var = (*var)->negatedvar;
12523  break;
12524 
12525  default:
12526  SCIPerrorMessage("unknown variable status\n");
12527  SCIPABORT();
12528  return SCIP_INVALIDDATA; /*lint !e527*/
12529  }
12530  }
12531  *scalar = 0.0;
12532 
12533  return SCIP_OKAY;
12534 }
12535 
12536 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12537  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12538  */
12540  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12541  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12542  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12543  )
12544 {
12545  SCIP_VAR* parentvar;
12546 
12547  assert(var != NULL);
12548  assert(*var != NULL);
12549  assert(scalar != NULL);
12550  assert(constant != NULL);
12551 
12552  while( !SCIPvarIsOriginal(*var) )
12553  {
12554  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12555  * var
12556  */
12557  if( (*var)->nparentvars == 0 )
12558  {
12559  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12560  * space
12561  */
12563  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12564  {
12565  *scalar *= -1.0;
12566  *constant -= (*var)->data.negate.constant * (*scalar);
12567  *var = (*var)->negatedvar;
12568 
12569  continue;
12570  }
12571  /* if the variables does not have any parent the variables was created during solving and has no original
12572  * counterpart
12573  */
12574  else
12575  {
12576  *var = NULL;
12577 
12578  return SCIP_OKAY;
12579  }
12580  }
12581 
12582  /* follow the link to the first parent variable */
12583  parentvar = (*var)->parentvars[0];
12584  assert(parentvar != NULL);
12585 
12586  switch( SCIPvarGetStatus(parentvar) )
12587  {
12589  break;
12590 
12591  case SCIP_VARSTATUS_COLUMN:
12592  case SCIP_VARSTATUS_LOOSE:
12593  case SCIP_VARSTATUS_FIXED:
12595  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12596  return SCIP_INVALIDDATA;
12597 
12598  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12599  assert(parentvar->data.aggregate.var == *var);
12600  assert(parentvar->data.aggregate.scalar != 0.0);
12601  *scalar /= parentvar->data.aggregate.scalar;
12602  *constant -= parentvar->data.aggregate.constant * (*scalar);
12603  break;
12604 
12605  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12606  assert(parentvar->negatedvar != NULL);
12607  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12608  assert(parentvar->negatedvar->negatedvar == parentvar);
12609  *scalar *= -1.0;
12610  *constant -= parentvar->data.negate.constant * (*scalar);
12611  break;
12612 
12613  default:
12614  SCIPerrorMessage("unknown variable status\n");
12615  return SCIP_INVALIDDATA;
12616  }
12617 
12618  assert( parentvar != NULL );
12619  *var = parentvar;
12620  }
12621 
12622  return SCIP_OKAY;
12623 }
12624 
12625 /** returns whether the given variable is the direct counterpart of an original problem variable */
12627  SCIP_VAR* var /**< problem variable */
12628  )
12629 {
12630  SCIP_VAR* parentvar;
12631  assert(var != NULL);
12632 
12633  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12634  return FALSE;
12635 
12636  assert(var->parentvars != NULL);
12637  parentvar = var->parentvars[0];
12638  assert(parentvar != NULL);
12639 
12640  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12641  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12642  parentvar = parentvar->parentvars[0];
12643  assert( parentvar != NULL );
12644 
12645  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12646 }
12647 
12648 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12649  * the variable's own data due to diving, that operate only on the LP without updating the variables
12650  */
12652  SCIP_VAR* var /**< problem variable */
12653  )
12654 {
12655  assert(var != NULL);
12656 
12657  /* get bounds of attached variables */
12658  switch( SCIPvarGetStatus(var) )
12659  {
12661  assert(var->data.original.transvar != NULL);
12662  return SCIPvarGetObjLP(var->data.original.transvar);
12663 
12664  case SCIP_VARSTATUS_COLUMN:
12665  assert(var->data.col != NULL);
12666  return SCIPcolGetObj(var->data.col);
12667 
12668  case SCIP_VARSTATUS_LOOSE:
12669  case SCIP_VARSTATUS_FIXED:
12670  return var->obj;
12671 
12672  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12673  assert(var->data.aggregate.var != NULL);
12674  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12675 
12677  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12678  SCIPABORT();
12679  return 0.0; /*lint !e527*/
12680 
12681  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12682  assert(var->negatedvar != NULL);
12684  assert(var->negatedvar->negatedvar == var);
12685  return -SCIPvarGetObjLP(var->negatedvar);
12686 
12687  default:
12688  SCIPerrorMessage("unknown variable status\n");
12689  SCIPABORT();
12690  return 0.0; /*lint !e527*/
12691  }
12692 }
12693 
12694 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12695  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12696  */
12698  SCIP_VAR* var, /**< problem variable */
12699  SCIP_SET* set /**< global SCIP settings */
12700  )
12701 {
12702  assert(var != NULL);
12703  assert(set != NULL);
12704  assert(var->scip == set->scip);
12705 
12706  /* get bounds of attached variables */
12707  switch( SCIPvarGetStatus(var) )
12708  {
12710  assert(var->data.original.transvar != NULL);
12711  return SCIPvarGetLbLP(var->data.original.transvar, set);
12712 
12713  case SCIP_VARSTATUS_COLUMN:
12714  assert(var->data.col != NULL);
12715  return SCIPcolGetLb(var->data.col);
12716 
12717  case SCIP_VARSTATUS_LOOSE:
12718  case SCIP_VARSTATUS_FIXED:
12719  return var->locdom.lb;
12720 
12721  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12722  assert(var->data.aggregate.var != NULL);
12723  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12724  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12725  {
12726  return -SCIPsetInfinity(set);
12727  }
12728  else if( var->data.aggregate.scalar > 0.0 )
12729  {
12730  /* a > 0 -> get lower bound of y */
12731  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12732  }
12733  else if( var->data.aggregate.scalar < 0.0 )
12734  {
12735  /* a < 0 -> get upper bound of y */
12736  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12737  }
12738  else
12739  {
12740  SCIPerrorMessage("scalar is zero in aggregation\n");
12741  SCIPABORT();
12742  return SCIP_INVALID; /*lint !e527*/
12743  }
12744 
12746  /**@todo get the sides of the corresponding linear constraint */
12747  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12748  SCIPABORT();
12749  return SCIP_INVALID; /*lint !e527*/
12750 
12751  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12752  assert(var->negatedvar != NULL);
12754  assert(var->negatedvar->negatedvar == var);
12755  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12756 
12757  default:
12758  SCIPerrorMessage("unknown variable status\n");
12759  SCIPABORT();
12760  return SCIP_INVALID; /*lint !e527*/
12761  }
12762 }
12763 
12764 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12765  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12766  */
12768  SCIP_VAR* var, /**< problem variable */
12769  SCIP_SET* set /**< global SCIP settings */
12770  )
12771 {
12772  assert(var != NULL);
12773  assert(set != NULL);
12774  assert(var->scip == set->scip);
12775 
12776  /* get bounds of attached variables */
12777  switch( SCIPvarGetStatus(var) )
12778  {
12780  assert(var->data.original.transvar != NULL);
12781  return SCIPvarGetUbLP(var->data.original.transvar, set);
12782 
12783  case SCIP_VARSTATUS_COLUMN:
12784  assert(var->data.col != NULL);
12785  return SCIPcolGetUb(var->data.col);
12786 
12787  case SCIP_VARSTATUS_LOOSE:
12788  case SCIP_VARSTATUS_FIXED:
12789  return var->locdom.ub;
12790 
12791  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12792  assert(var->data.aggregate.var != NULL);
12793  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12794  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12795  {
12796  return SCIPsetInfinity(set);
12797  }
12798  if( var->data.aggregate.scalar > 0.0 )
12799  {
12800  /* a > 0 -> get upper bound of y */
12801  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12802  }
12803  else if( var->data.aggregate.scalar < 0.0 )
12804  {
12805  /* a < 0 -> get lower bound of y */
12806  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12807  }
12808  else
12809  {
12810  SCIPerrorMessage("scalar is zero in aggregation\n");
12811  SCIPABORT();
12812  return SCIP_INVALID; /*lint !e527*/
12813  }
12814 
12816  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12817  SCIPABORT();
12818  return SCIP_INVALID; /*lint !e527*/
12819 
12820  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12821  assert(var->negatedvar != NULL);
12823  assert(var->negatedvar->negatedvar == var);
12824  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12825 
12826  default:
12827  SCIPerrorMessage("unknown variable status\n");
12828  SCIPABORT();
12829  return SCIP_INVALID; /*lint !e527*/
12830  }
12831 }
12832 
12833 /** gets primal LP solution value of variable */
12835  SCIP_VAR* var /**< problem variable */
12836  )
12837 {
12838  assert(var != NULL);
12839 
12840  switch( SCIPvarGetStatus(var) )
12841  {
12843  if( var->data.original.transvar == NULL )
12844  return SCIP_INVALID;
12845  return SCIPvarGetLPSol(var->data.original.transvar);
12846 
12847  case SCIP_VARSTATUS_LOOSE:
12848  return SCIPvarGetBestBoundLocal(var);
12849 
12850  case SCIP_VARSTATUS_COLUMN:
12851  assert(var->data.col != NULL);
12852  return SCIPcolGetPrimsol(var->data.col);
12853 
12854  case SCIP_VARSTATUS_FIXED:
12855  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12856  return var->locdom.lb;
12857 
12859  {
12860  SCIP_Real lpsolval;
12861 
12862  assert(var->data.aggregate.var != NULL);
12863  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12864 
12865  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12866  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12867  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12868  * (or is called by) a public interface method; instead, we only assert that values are finite
12869  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12870  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12871  */
12872  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12873  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12874  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12875  }
12877  {
12878  SCIP_Real primsol;
12879  int i;
12880 
12881  assert(!var->donotmultaggr);
12882  assert(var->data.multaggr.vars != NULL);
12883  assert(var->data.multaggr.scalars != NULL);
12884  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12885  * assert(var->data.multaggr.nvars >= 2);
12886  */
12887  primsol = var->data.multaggr.constant;
12888  for( i = 0; i < var->data.multaggr.nvars; ++i )
12889  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12890  return primsol;
12891  }
12892  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12893  assert(var->negatedvar != NULL);
12895  assert(var->negatedvar->negatedvar == var);
12896  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12897 
12898  default:
12899  SCIPerrorMessage("unknown variable status\n");
12900  SCIPABORT();
12901  return SCIP_INVALID; /*lint !e527*/
12902  }
12903 }
12904 
12905 /** gets primal NLP solution value of variable */
12907  SCIP_VAR* var /**< problem variable */
12908  )
12909 {
12910  SCIP_Real solval;
12911  int i;
12912 
12913  assert(var != NULL);
12914 
12915  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12916  switch( SCIPvarGetStatus(var) )
12917  {
12919  return SCIPvarGetNLPSol(var->data.original.transvar);
12920 
12921  case SCIP_VARSTATUS_LOOSE:
12922  case SCIP_VARSTATUS_COLUMN:
12923  return var->nlpsol;
12924 
12925  case SCIP_VARSTATUS_FIXED:
12926  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12927  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12928  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12929  return SCIPvarGetLbGlobal(var);
12930 
12931  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12932  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12933  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12934 
12936  solval = var->data.multaggr.constant;
12937  for( i = 0; i < var->data.multaggr.nvars; ++i )
12938  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12939  return solval;
12940 
12942  solval = SCIPvarGetNLPSol(var->negatedvar);
12943  return var->data.negate.constant - solval;
12944 
12945  default:
12946  SCIPerrorMessage("unknown variable status\n");
12947  SCIPABORT();
12948  return SCIP_INVALID; /*lint !e527*/
12949  }
12950 }
12951 
12952 /** gets pseudo solution value of variable at current node */
12953 static
12955  SCIP_VAR* var /**< problem variable */
12956  )
12957 {
12958  SCIP_Real pseudosol;
12959  int i;
12960 
12961  assert(var != NULL);
12962 
12963  switch( SCIPvarGetStatus(var) )
12964  {
12966  if( var->data.original.transvar == NULL )
12967  return SCIP_INVALID;
12969 
12970  case SCIP_VARSTATUS_LOOSE:
12971  case SCIP_VARSTATUS_COLUMN:
12972  return SCIPvarGetBestBoundLocal(var);
12973 
12974  case SCIP_VARSTATUS_FIXED:
12975  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12976  return var->locdom.lb;
12977 
12979  {
12980  SCIP_Real pseudosolval;
12981  assert(var->data.aggregate.var != NULL);
12982  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12983  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12984  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12985  * (or is called by) a public interface method; instead, we only assert that values are finite
12986  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12987  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12988  */
12989  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12990  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12991  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12992  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12993  }
12995  assert(!var->donotmultaggr);
12996  assert(var->data.multaggr.vars != NULL);
12997  assert(var->data.multaggr.scalars != NULL);
12998  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12999  * assert(var->data.multaggr.nvars >= 2);
13000  */
13001  pseudosol = var->data.multaggr.constant;
13002  for( i = 0; i < var->data.multaggr.nvars; ++i )
13003  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13004  return pseudosol;
13005 
13006  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13007  assert(var->negatedvar != NULL);
13009  assert(var->negatedvar->negatedvar == var);
13010  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13011 
13012  default:
13013  SCIPerrorMessage("unknown variable status\n");
13014  SCIPABORT();
13015  return SCIP_INVALID; /*lint !e527*/
13016  }
13017 }
13018 
13019 /** gets current LP or pseudo solution value of variable */
13021  SCIP_VAR* var, /**< problem variable */
13022  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13023  )
13024 {
13025  if( getlpval )
13026  return SCIPvarGetLPSol(var);
13027  else
13028  return SCIPvarGetPseudoSol(var);
13029 }
13030 
13031 /** remembers the current solution as root solution in the problem variables */
13032 void SCIPvarStoreRootSol(
13033  SCIP_VAR* var, /**< problem variable */
13034  SCIP_Bool roothaslp /**< is the root solution from LP? */
13035  )
13036 {
13037  assert(var != NULL);
13038 
13039  var->rootsol = SCIPvarGetSol(var, roothaslp);
13040 }
13041 
13042 /** updates the current solution as best root solution of the given variable if it is better */
13044  SCIP_VAR* var, /**< problem variable */
13045  SCIP_SET* set, /**< global SCIP settings */
13046  SCIP_Real rootsol, /**< root solution value */
13047  SCIP_Real rootredcost, /**< root reduced cost */
13048  SCIP_Real rootlpobjval /**< objective value of the root LP */
13049  )
13050 {
13051  assert(var != NULL);
13052  assert(set != NULL);
13053  assert(var->scip == set->scip);
13054 
13055  /* if reduced cost are zero nothing to update */
13056  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13057  return;
13058 
13059  /* check if we have already a best combination stored */
13060  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13061  {
13062  SCIP_Real currcutoffbound;
13063  SCIP_Real cutoffbound;
13064  SCIP_Real bound;
13065 
13066  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13067  * root reduced cost, and root LP objective value combination
13068  */
13069  if( var->bestrootredcost > 0.0 )
13070  bound = SCIPvarGetUbGlobal(var);
13071  else
13072  bound = SCIPvarGetLbGlobal(var);
13073 
13074  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13075 
13076  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13077  * cost, and root LP objective value combination
13078  */
13079  if( rootredcost > 0.0 )
13080  bound = SCIPvarGetUbGlobal(var);
13081  else
13082  bound = SCIPvarGetLbGlobal(var);
13083 
13084  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13085 
13086  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13087  if( cutoffbound > currcutoffbound )
13088  {
13089  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13090  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13091 
13092  var->bestrootsol = rootsol;
13093  var->bestrootredcost = rootredcost;
13094  var->bestrootlpobjval = rootlpobjval;
13095  }
13096  }
13097  else
13098  {
13099  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13100  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13101  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13102  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13103 
13104  var->bestrootsol = rootsol;
13105  var->bestrootredcost = rootredcost;
13106  var->bestrootlpobjval = rootlpobjval;
13107  }
13108 }
13109 
13110 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13111  * completely solved, zero is returned
13112  */
13114  SCIP_VAR* var /**< problem variable */
13115  )
13116 {
13117  SCIP_Real rootsol;
13118  int i;
13119 
13120  assert(var != NULL);
13121 
13122  switch( SCIPvarGetStatus(var) )
13123  {
13125  if( var->data.original.transvar == NULL )
13126  return 0.0;
13127  return SCIPvarGetRootSol(var->data.original.transvar);
13128 
13129  case SCIP_VARSTATUS_LOOSE:
13130  case SCIP_VARSTATUS_COLUMN:
13131  return var->rootsol;
13132 
13133  case SCIP_VARSTATUS_FIXED:
13134  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13135  return var->locdom.lb;
13136 
13138  assert(var->data.aggregate.var != NULL);
13139  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13140  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13141  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13142  * (or is called by) a public interface method; instead, we only assert that values are finite
13143  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13144  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13145  */
13149 
13151  assert(!var->donotmultaggr);
13152  assert(var->data.multaggr.vars != NULL);
13153  assert(var->data.multaggr.scalars != NULL);
13154  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13155  * assert(var->data.multaggr.nvars >= 2);
13156  */
13157  rootsol = var->data.multaggr.constant;
13158  for( i = 0; i < var->data.multaggr.nvars; ++i )
13159  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13160  return rootsol;
13161 
13162  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13163  assert(var->negatedvar != NULL);
13165  assert(var->negatedvar->negatedvar == var);
13166  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13167 
13168  default:
13169  SCIPerrorMessage("unknown variable status\n");
13170  SCIPABORT();
13171  return SCIP_INVALID; /*lint !e527*/
13172  }
13173 }
13174 
13175 /** returns for given variable the reduced cost */
13176 static
13178  SCIP_VAR* var, /**< problem variable */
13179  SCIP_SET* set, /**< global SCIP settings */
13180  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13181  SCIP_STAT* stat, /**< problem statistics */
13182  SCIP_LP* lp /**< current LP data */
13183  )
13184 {
13186  {
13187  SCIP_COL* col;
13188  SCIP_Real primsol;
13189  SCIP_BASESTAT basestat;
13190  SCIP_Bool lpissolbasic;
13191 
13192  col = SCIPvarGetCol(var);
13193  assert(col != NULL);
13194 
13195  basestat = SCIPcolGetBasisStatus(col);
13196  lpissolbasic = SCIPlpIsSolBasic(lp);
13197  primsol = SCIPcolGetPrimsol(col);
13198 
13199  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13200  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13201  {
13202  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13203 
13204  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13205  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13207  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13208  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13209  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13210 
13211  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13212  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13213  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13214  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13215  return redcost;
13216  else
13217  return 0.0;
13218  }
13219 
13220  return 0.0;
13221  }
13222 
13223  return 0.0;
13224 }
13225 
13226 #define MAX_CLIQUELENGTH 50
13227 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13228  * the binary variable is fixed to the given value
13229  */
13231  SCIP_VAR* var, /**< problem variable */
13232  SCIP_SET* set, /**< global SCIP settings */
13233  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13234  SCIP_STAT* stat, /**< problem statistics */
13235  SCIP_PROB* prob, /**< transformed problem, or NULL */
13236  SCIP_LP* lp /**< current LP data */
13237  )
13238 {
13239  SCIP_Real implredcost;
13240  int ncliques;
13241  int nvars;
13242 
13243  assert(SCIPvarIsBinary(var));
13244  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13245 
13246  /* get reduced cost of given variable */
13247  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13248 
13249 #ifdef SCIP_MORE_DEBUG
13250  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13251 #endif
13252 
13253  /* the following algorithm is expensive */
13254  ncliques = SCIPvarGetNCliques(var, varfixing);
13255 
13256  if( ncliques > 0 )
13257  {
13258  SCIP_CLIQUE** cliques;
13259  SCIP_CLIQUE* clique;
13260  SCIP_VAR** clqvars;
13261  SCIP_VAR** probvars;
13262  SCIP_VAR* clqvar;
13263  SCIP_Bool* clqvalues;
13264  int* entries;
13265  int* ids;
13266  SCIP_Real redcost;
13267  SCIP_Bool cleanedup;
13268  int nclqvars;
13269  int nentries;
13270  int nids;
13271  int id;
13272  int c;
13273  int v;
13274 
13275  assert(prob != NULL);
13276  assert(SCIPprobIsTransformed(prob));
13277 
13278  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13279 
13280  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13281  nids = 0;
13282  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13283 
13284  cliques = SCIPvarGetCliques(var, varfixing);
13285  assert(cliques != NULL);
13286 
13287  for( c = ncliques - 1; c >= 0; --c )
13288  {
13289  clique = cliques[c];
13290  assert(clique != NULL);
13291  nclqvars = SCIPcliqueGetNVars(clique);
13292  assert(nclqvars > 0);
13293 
13294  if( nclqvars > MAX_CLIQUELENGTH )
13295  continue;
13296 
13297  clqvars = SCIPcliqueGetVars(clique);
13298  clqvalues = SCIPcliqueGetValues(clique);
13299  assert(clqvars != NULL);
13300  assert(clqvalues != NULL);
13301 
13302  cleanedup = SCIPcliqueIsCleanedUp(clique);
13303 
13304  for( v = nclqvars - 1; v >= 0; --v )
13305  {
13306  clqvar = clqvars[v];
13307  assert(clqvar != NULL);
13308 
13309  /* ignore binary variable which are fixed */
13310  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13311  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13312  {
13313  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13314  assert(0 < probindex && probindex < nentries);
13315 
13316 #if 0
13317  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13318  * can appear since there is no guarantee that all these infeasible bounds were found
13319  */
13320  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13321 #endif
13322  if( entries[probindex] == 0 )
13323  {
13324  ids[nids] = probindex;
13325  ++nids;
13326 
13327  /* mark variable as visited */
13328  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13329  }
13330  }
13331  }
13332  }
13333 
13334  probvars = SCIPprobGetVars(prob);
13335  assert(probvars != NULL);
13336 
13337  /* add all implied reduced cost */
13338  for( v = nids - 1; v >= 0; --v )
13339  {
13340  id = ids[v];
13341  assert(0 < id && id < nentries);
13342  assert(entries[id] != 0);
13343  assert(probvars[id - 1] != NULL);
13344  assert(SCIPvarIsActive(probvars[id - 1]));
13345  assert(SCIPvarIsBinary(probvars[id - 1]));
13346  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13347 
13348  if( (entries[id] > 0) != varfixing )
13349  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13350  else
13351  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13352 
13353  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13354  implredcost += redcost;
13355 
13356  /* reset entries clear buffer array */
13357  entries[id] = 0;
13358  }
13359 
13360  SCIPsetFreeCleanBufferArray(set, &entries);
13361  SCIPsetFreeBufferArray(set, &ids);
13362  }
13363 
13364 #ifdef SCIP_MORE_DEBUG
13365  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13366  implredcost);
13367 #endif
13368 
13369  /* collect non-binary implication information */
13370  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13371 
13372  if( nvars > 0 )
13373  {
13374  SCIP_VAR** vars;
13375  SCIP_VAR* implvar;
13376  SCIP_COL* col;
13377  SCIP_Real* bounds;
13378  SCIP_BOUNDTYPE* boundtypes;
13379  SCIP_Real redcost;
13380  SCIP_Real lb;
13381  SCIP_Real ub;
13382  SCIP_Bool lpissolbasic;
13383  int v;
13384 
13385  vars = SCIPimplicsGetVars(var->implics, varfixing);
13386  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13387  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13388  lpissolbasic = SCIPlpIsSolBasic(lp);
13389 
13390  for( v = nvars - 1; v >= 0; --v )
13391  {
13392  implvar = vars[v];
13393  assert(implvar != NULL);
13394 
13395  lb = SCIPvarGetLbLocal(implvar);
13396  ub = SCIPvarGetUbLocal(implvar);
13397 
13398  /* ignore binary variable which are fixed or not of column status */
13399  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13400  continue;
13401 
13402  col = SCIPvarGetCol(implvar);
13403  assert(col != NULL);
13404  redcost = 0.0;
13405 
13406  /* solved lp with basis information or not? */
13407  if( lpissolbasic )
13408  {
13409  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13410 
13411  /* check if the implication is not not yet applied */
13412  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13413  {
13414  redcost = SCIPcolGetRedcost(col, stat, lp);
13415  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13416 
13417  if( !varfixing )
13418  redcost *= (lb - bounds[v]);
13419  else
13420  redcost *= (bounds[v] - lb);
13421  }
13422  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13423  {
13424  redcost = SCIPcolGetRedcost(col, stat, lp);
13425  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13426 
13427  if( varfixing )
13428  redcost *= (bounds[v] - ub);
13429  else
13430  redcost *= (ub - bounds[v]);
13431  }
13432  }
13433  else
13434  {
13435  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13436 
13437  /* check if the implication is not not yet applied */
13438  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13439  {
13440  redcost = SCIPcolGetRedcost(col, stat, lp);
13441  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13442 
13443  if( varfixing )
13444  redcost *= (lb - bounds[v]);
13445  else
13446  redcost *= (bounds[v] - lb);
13447  }
13448  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13449  {
13450  redcost = SCIPcolGetRedcost(col, stat, lp);
13451  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13452 
13453  if( varfixing )
13454  redcost *= (bounds[v] - ub);
13455  else
13456  redcost *= (ub - bounds[v]);
13457  }
13458  }
13459 
13460  /* improve implied reduced cost */
13461  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13462  implredcost += redcost;
13463  }
13464  }
13465 
13466 #ifdef SCIP_MORE_DEBUG
13467  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13468  SCIPvarGetName(var), ncliques, nvars, implredcost);
13469 #endif
13470 
13471  return implredcost;
13472 }
13473 
13474 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13475  * the root relaxation is not yet completely solved, zero is returned
13476  */
13478  SCIP_VAR* var /**< problem variable */
13479  )
13480 {
13481  SCIP_Real rootsol;
13482  int i;
13483 
13484  assert(var != NULL);
13485 
13486  switch( SCIPvarGetStatus(var) )
13487  {
13489  if( var->data.original.transvar == NULL )
13490  return 0.0;
13492 
13493  case SCIP_VARSTATUS_LOOSE:
13494  case SCIP_VARSTATUS_COLUMN:
13495  return var->bestrootsol;
13496 
13497  case SCIP_VARSTATUS_FIXED:
13498  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13499  return var->locdom.lb;
13500 
13502  assert(var->data.aggregate.var != NULL);
13503  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13504  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13505  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13506  * (or is called by) a public interface method; instead, we only assert that values are finite
13507  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13508  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13509  */
13513 
13515  assert(!var->donotmultaggr);
13516  assert(var->data.multaggr.vars != NULL);
13517  assert(var->data.multaggr.scalars != NULL);
13518  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13519  * assert(var->data.multaggr.nvars >= 2);
13520  */
13521  rootsol = var->data.multaggr.constant;
13522  for( i = 0; i < var->data.multaggr.nvars; ++i )
13523  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13524  return rootsol;
13525 
13526  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13527  assert(var->negatedvar != NULL);
13529  assert(var->negatedvar->negatedvar == var);
13530  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13531 
13532  default:
13533  SCIPerrorMessage("unknown variable status\n");
13534  SCIPABORT();
13535  return 0.0; /*lint !e527*/
13536  }
13537 }
13538 
13539 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13540  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13541  * returned
13542  */
13544  SCIP_VAR* var /**< problem variable */
13545  )
13546 {
13547  assert(var != NULL);
13548 
13549  switch( SCIPvarGetStatus(var) )
13550  {
13552  if( var->data.original.transvar == NULL )
13553  return SCIP_INVALID;
13555 
13556  case SCIP_VARSTATUS_LOOSE:
13557  case SCIP_VARSTATUS_COLUMN:
13558  return var->bestrootredcost;
13559 
13560  case SCIP_VARSTATUS_FIXED:
13564  return 0.0;
13565 
13566  default:
13567  SCIPerrorMessage("unknown variable status\n");
13568  SCIPABORT();
13569  return 0.0; /*lint !e527*/
13570  }
13571 }
13572 
13573 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13574  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13575  * SCIP_INVALID is returned
13576  */
13578  SCIP_VAR* var /**< problem variable */
13579  )
13580 {
13581  assert(var != NULL);
13582 
13583  switch( SCIPvarGetStatus(var) )
13584  {
13586  if( var->data.original.transvar == NULL )
13587  return SCIP_INVALID;
13589 
13590  case SCIP_VARSTATUS_LOOSE:
13591  case SCIP_VARSTATUS_COLUMN:
13592  return var->bestrootlpobjval;
13593 
13594  case SCIP_VARSTATUS_FIXED:
13598  return SCIP_INVALID;
13599 
13600  default:
13601  SCIPerrorMessage("unknown variable status\n");
13602  SCIPABORT();
13603  return SCIP_INVALID; /*lint !e527*/
13604  }
13605 }
13606 
13607 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13609  SCIP_VAR* var, /**< problem variable */
13610  SCIP_Real rootsol, /**< root solution value */
13611  SCIP_Real rootredcost, /**< root reduced cost */
13612  SCIP_Real rootlpobjval /**< objective value of the root LP */
13613  )
13614 {
13615  assert(var != NULL);
13616 
13617  var->bestrootsol = rootsol;
13618  var->bestrootredcost = rootredcost;
13619  var->bestrootlpobjval = rootlpobjval;
13620 }
13621 
13622 /** stores the solution value as relaxation solution in the problem variable */
13624  SCIP_VAR* var, /**< problem variable */
13625  SCIP_SET* set, /**< global SCIP settings */
13626  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13627  SCIP_Real solval, /**< solution value in the current relaxation solution */
13628  SCIP_Bool updateobj /**< should the objective value be updated? */
13629  )
13630 {
13631  assert(var != NULL);
13632  assert(relaxation != NULL);
13633  assert(set != NULL);
13634  assert(var->scip == set->scip);
13635 
13636  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13637  switch( SCIPvarGetStatus(var) )
13638  {
13640  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13641  break;
13642 
13643  case SCIP_VARSTATUS_LOOSE:
13644  case SCIP_VARSTATUS_COLUMN:
13645  if( updateobj )
13646  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13647  var->relaxsol = solval;
13648  break;
13649 
13650  case SCIP_VARSTATUS_FIXED:
13651  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13652  {
13653  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13654  SCIPvarGetName(var), var->glbdom.lb, solval);
13655  return SCIP_INVALIDDATA;
13656  }
13657  break;
13658 
13659  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13660  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13661  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13662  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13663  break;
13665  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13666  return SCIP_INVALIDDATA;
13667 
13669  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13670  break;
13671 
13672  default:
13673  SCIPerrorMessage("unknown variable status\n");
13674  return SCIP_INVALIDDATA;
13675  }
13676 
13677  return SCIP_OKAY;
13678 }
13679 
13680 /** returns the solution value of the problem variable in the relaxation solution
13681  *
13682  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13683  */
13685  SCIP_VAR* var, /**< problem variable */
13686  SCIP_SET* set /**< global SCIP settings */
13687  )
13688 {
13689  SCIP_Real solvalsum;
13690  SCIP_Real solval;
13691  int i;
13692 
13693  assert(var != NULL);
13694  assert(set != NULL);
13695  assert(var->scip == set->scip);
13696 
13697  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13698  switch( SCIPvarGetStatus(var) )
13699  {
13701  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13702 
13703  case SCIP_VARSTATUS_LOOSE:
13704  case SCIP_VARSTATUS_COLUMN:
13705  return var->relaxsol;
13706 
13707  case SCIP_VARSTATUS_FIXED:
13708  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13709  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13710  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13711  return SCIPvarGetLbGlobal(var);
13712 
13713  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13714  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13715  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13716  {
13717  if( var->data.aggregate.scalar * solval > 0.0 )
13718  return SCIPsetInfinity(set);
13719  if( var->data.aggregate.scalar * solval < 0.0 )
13720  return -SCIPsetInfinity(set);
13721  }
13722  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13723 
13725  solvalsum = var->data.multaggr.constant;
13726  for( i = 0; i < var->data.multaggr.nvars; ++i )
13727  {
13728  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13729  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13730  {
13731  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13732  return SCIPsetInfinity(set);
13733  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13734  return -SCIPsetInfinity(set);
13735  }
13736  solvalsum += var->data.multaggr.scalars[i] * solval;
13737  }
13738  return solvalsum;
13739 
13741  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13742  if( SCIPsetIsInfinity(set, solval) )
13743  return -SCIPsetInfinity(set);
13744  if( SCIPsetIsInfinity(set, -solval) )
13745  return SCIPsetInfinity(set);
13746  return var->data.negate.constant - solval;
13747 
13748  default:
13749  SCIPerrorMessage("unknown variable status\n");
13750  SCIPABORT();
13751  return SCIP_INVALID; /*lint !e527*/
13752  }
13753 }
13754 
13755 /** returns the solution value of the transformed problem variable in the relaxation solution */
13757  SCIP_VAR* var /**< problem variable */
13758  )
13759 {
13760  assert(var != NULL);
13762 
13763  return var->relaxsol;
13764 }
13765 
13766 /** stores the solution value as NLP solution in the problem variable */
13768  SCIP_VAR* var, /**< problem variable */
13769  SCIP_SET* set, /**< global SCIP settings */
13770  SCIP_Real solval /**< solution value in the current NLP solution */
13771  )
13772 {
13773  assert(var != NULL);
13774  assert(set != NULL);
13775  assert(var->scip == set->scip);
13776 
13777  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13778  switch( SCIPvarGetStatus(var) )
13779  {
13781  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13782  break;
13783 
13784  case SCIP_VARSTATUS_LOOSE:
13785  case SCIP_VARSTATUS_COLUMN:
13786  var->nlpsol = solval;
13787  break;
13788 
13789  case SCIP_VARSTATUS_FIXED:
13790  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13791  {
13792  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13793  SCIPvarGetName(var), var->glbdom.lb, solval);
13794  SCIPABORT();
13795  return SCIP_INVALIDCALL; /*lint !e527*/
13796  }
13797  break;
13798 
13799  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13800  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13801  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13802  break;
13803 
13805  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13806  SCIPABORT();
13807  return SCIP_INVALIDCALL; /*lint !e527*/
13808 
13810  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13811  break;
13812 
13813  default:
13814  SCIPerrorMessage("unknown variable status\n");
13815  SCIPABORT();
13816  return SCIP_ERROR; /*lint !e527*/
13817  }
13818 
13819  return SCIP_OKAY;
13820 }
13821 
13822 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13824  SCIP_VAR* var /**< problem variable */
13825  )
13826 {
13827  SCIP_Real avgsol;
13828  int i;
13829 
13830  assert(var != NULL);
13831 
13832  switch( SCIPvarGetStatus(var) )
13833  {
13835  if( var->data.original.transvar == NULL )
13836  return 0.0;
13837  return SCIPvarGetAvgSol(var->data.original.transvar);
13838 
13839  case SCIP_VARSTATUS_LOOSE:
13840  case SCIP_VARSTATUS_COLUMN:
13841  avgsol = var->primsolavg;
13842  avgsol = MAX(avgsol, var->glbdom.lb);
13843  avgsol = MIN(avgsol, var->glbdom.ub);
13844  return avgsol;
13845 
13846  case SCIP_VARSTATUS_FIXED:
13847  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13848  return var->locdom.lb;
13849 
13851  assert(var->data.aggregate.var != NULL);
13852  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13853  + var->data.aggregate.constant;
13854 
13856  assert(!var->donotmultaggr);
13857  assert(var->data.multaggr.vars != NULL);
13858  assert(var->data.multaggr.scalars != NULL);
13859  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13860  * assert(var->data.multaggr.nvars >= 2);
13861  */
13862  avgsol = var->data.multaggr.constant;
13863  for( i = 0; i < var->data.multaggr.nvars; ++i )
13864  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13865  return avgsol;
13866 
13867  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13868  assert(var->negatedvar != NULL);
13870  assert(var->negatedvar->negatedvar == var);
13871  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13872 
13873  default:
13874  SCIPerrorMessage("unknown variable status\n");
13875  SCIPABORT();
13876  return 0.0; /*lint !e527*/
13877  }
13878 }
13879 
13880 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13881  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13882  */
13884  SCIP_VAR* var, /**< active problem variable */
13885  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13886  SCIP_SET* set, /**< global SCIP settings */
13887  SCIP_STAT* stat, /**< problem statistics */
13888  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13889  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13890  )
13891 {
13892  int nvlbs;
13893 
13894  assert(var != NULL);
13895  assert(stat != NULL);
13896  assert(set != NULL);
13897  assert(var->scip == set->scip);
13898  assert(closestvlb != NULL);
13899  assert(closestvlbidx != NULL);
13900 
13901  *closestvlbidx = -1;
13902  *closestvlb = SCIP_REAL_MIN;
13903 
13904  nvlbs = SCIPvarGetNVlbs(var);
13905  if( nvlbs > 0 )
13906  {
13907  SCIP_VAR** vlbvars;
13908  SCIP_Real* vlbcoefs;
13909  SCIP_Real* vlbconsts;
13910  int i;
13911 
13912  vlbvars = SCIPvarGetVlbVars(var);
13913  vlbcoefs = SCIPvarGetVlbCoefs(var);
13914  vlbconsts = SCIPvarGetVlbConstants(var);
13915 
13916  /* check for cached values */
13917  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13918  {
13919  i = var->closestvlbidx;
13920  assert(0 <= i && i < nvlbs);
13921  assert(SCIPvarIsActive(vlbvars[i]));
13922  *closestvlbidx = i;
13923  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13924  }
13925  else
13926  {
13927  /* search best VUB */
13928  for( i = 0; i < nvlbs; i++ )
13929  {
13930  if( SCIPvarIsActive(vlbvars[i]) )
13931  {
13932  SCIP_Real vlbsol;
13933 
13934  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13935  if( vlbsol > *closestvlb )
13936  {
13937  *closestvlb = vlbsol;
13938  *closestvlbidx = i;
13939  }
13940  }
13941  }
13942 
13943  if( sol == NULL )
13944  {
13945  /* update cached value */
13946  if( var->closestvblpcount != stat->lpcount )
13947  var->closestvubidx = -1;
13948  var->closestvlbidx = *closestvlbidx;
13949  var->closestvblpcount = stat->lpcount;
13950  }
13951  }
13952  }
13953 }
13954 
13955 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13956  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13957  */
13959  SCIP_VAR* var, /**< active problem variable */
13960  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13961  SCIP_SET* set, /**< global SCIP settings */
13962  SCIP_STAT* stat, /**< problem statistics */
13963  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13964  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13965  )
13966 {
13967  int nvubs;
13968 
13969  assert(var != NULL);
13970  assert(set != NULL);
13971  assert(var->scip == set->scip);
13972  assert(closestvub != NULL);
13973  assert(closestvubidx != NULL);
13974 
13975  *closestvubidx = -1;
13976  *closestvub = SCIP_REAL_MAX;
13977 
13978  nvubs = SCIPvarGetNVubs(var);
13979  if( nvubs > 0 )
13980  {
13981  SCIP_VAR** vubvars;
13982  SCIP_Real* vubcoefs;
13983  SCIP_Real* vubconsts;
13984  int i;
13985 
13986  vubvars = SCIPvarGetVubVars(var);
13987  vubcoefs = SCIPvarGetVubCoefs(var);
13988  vubconsts = SCIPvarGetVubConstants(var);
13989 
13990  /* check for cached values */
13991  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13992  {
13993  i = var->closestvubidx;
13994  assert(0 <= i && i < nvubs);
13995  assert(SCIPvarIsActive(vubvars[i]));
13996  *closestvubidx = i;
13997  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13998  }
13999  else
14000  {
14001  /* search best VUB */
14002  for( i = 0; i < nvubs; i++ )
14003  {
14004  if( SCIPvarIsActive(vubvars[i]) )
14005  {
14006  SCIP_Real vubsol;
14007 
14008  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14009  if( vubsol < *closestvub )
14010  {
14011  *closestvub = vubsol;
14012  *closestvubidx = i;
14013  }
14014  }
14015  }
14016 
14017  if( sol == NULL )
14018  {
14019  /* update cached value */
14020  if( var->closestvblpcount != stat->lpcount )
14021  var->closestvlbidx = -1;
14022  var->closestvubidx = *closestvubidx;
14023  var->closestvblpcount = stat->lpcount;
14024  }
14025  }
14026  }
14027 }
14028 
14029 /** resolves variable to columns and adds them with the coefficient to the row */
14031  SCIP_VAR* var, /**< problem variable */
14032  BMS_BLKMEM* blkmem, /**< block memory */
14033  SCIP_SET* set, /**< global SCIP settings */
14034  SCIP_STAT* stat, /**< problem statistics */
14035  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14036  SCIP_PROB* prob, /**< problem data */
14037  SCIP_LP* lp, /**< current LP data */
14038  SCIP_ROW* row, /**< LP row */
14039  SCIP_Real val /**< value of coefficient */
14040  )
14041 {
14042  int i;
14043 
14044  assert(var != NULL);
14045  assert(set != NULL);
14046  assert(var->scip == set->scip);
14047  assert(row != NULL);
14048  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14049 
14050  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14051 
14052  if ( SCIPsetIsZero(set, val) )
14053  return SCIP_OKAY;
14054 
14055  switch( SCIPvarGetStatus(var) )
14056  {
14058  if( var->data.original.transvar == NULL )
14059  {
14060  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14061  return SCIP_INVALIDDATA;
14062  }
14063  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14064  return SCIP_OKAY;
14065 
14066  case SCIP_VARSTATUS_LOOSE:
14067  /* add globally fixed variables as constant */
14068  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14069  {
14070  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14071  return SCIP_OKAY;
14072  }
14073  /* convert loose variable into column */
14074  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14075  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14076  /*lint -fallthrough*/
14077 
14078  case SCIP_VARSTATUS_COLUMN:
14079  assert(var->data.col != NULL);
14080  assert(var->data.col->var == var);
14081  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14082  return SCIP_OKAY;
14083 
14084  case SCIP_VARSTATUS_FIXED:
14085  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14086  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14087  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14088  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14089  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14090  return SCIP_OKAY;
14091 
14093  assert(var->data.aggregate.var != NULL);
14094  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14095  row, var->data.aggregate.scalar * val) );
14096  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14097  return SCIP_OKAY;
14098 
14100  assert(!var->donotmultaggr);
14101  assert(var->data.multaggr.vars != NULL);
14102  assert(var->data.multaggr.scalars != NULL);
14103  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14104  * assert(var->data.multaggr.nvars >= 2);
14105  */
14106  for( i = 0; i < var->data.multaggr.nvars; ++i )
14107  {
14108  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14109  row, var->data.multaggr.scalars[i] * val) );
14110  }
14111  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14112  return SCIP_OKAY;
14113 
14114  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14115  assert(var->negatedvar != NULL);
14117  assert(var->negatedvar->negatedvar == var);
14118  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14119  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14120  return SCIP_OKAY;
14121 
14122  default:
14123  SCIPerrorMessage("unknown variable status\n");
14124  return SCIP_INVALIDDATA;
14125  }
14126 }
14127 
14128 /* optionally, define this compiler flag to write complete variable histories to a file */
14129 #ifdef SCIP_HISTORYTOFILE
14130 SCIP_Longint counter = 0l;
14131 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14132 #include "scip/scip.h"
14133 #endif
14134 
14135 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14136  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14137  */
14139  SCIP_VAR* var, /**< problem variable */
14140  SCIP_SET* set, /**< global SCIP settings */
14141  SCIP_STAT* stat, /**< problem statistics */
14142  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14143  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14144  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14145  )
14146 {
14147  SCIP_Real oldrootpseudocosts;
14148  assert(var != NULL);
14149  assert(set != NULL);
14150  assert(var->scip == set->scip);
14151  assert(stat != NULL);
14152 
14153  /* check if history statistics should be collected for a variable */
14154  if( !stat->collectvarhistory )
14155  return SCIP_OKAY;
14156 
14157  switch( SCIPvarGetStatus(var) )
14158  {
14160  if( var->data.original.transvar == NULL )
14161  {
14162  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14163  return SCIP_INVALIDDATA;
14164  }
14165  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14166  return SCIP_OKAY;
14167 
14168  case SCIP_VARSTATUS_LOOSE:
14169  case SCIP_VARSTATUS_COLUMN:
14170  /* store old pseudo-costs for root LP best-estimate update */
14171  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14172 
14173  /* update history */
14174  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14175  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14176  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14177  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14178 
14179  /* update root LP best-estimate */
14180  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14181 
14182  /* append history to file */
14183 #ifdef SCIP_HISTORYTOFILE
14184  {
14185  FILE* f;
14186  char filename[256];
14187  SCIP_NODE* currentnode;
14188  SCIP_NODE* parentnode;
14189  currentnode = SCIPgetFocusNode(set->scip);
14190  parentnode = SCIPnodeGetParent(currentnode);
14191 
14192  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14193  f = fopen(filename, "a");
14194  if( NULL != f )
14195  {
14196  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14197  ++counter,
14198  SCIPvarGetName(var),
14199  SCIPnodeGetNumber(currentnode),
14200  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14201  SCIPgetNLPIterations(set->scip),
14202  SCIPgetDepth(set->scip),
14203  objdelta,
14204  solvaldelta);
14205  fclose(f);
14206  }
14207  }
14208 #endif
14209  return SCIP_OKAY;
14210 
14211  case SCIP_VARSTATUS_FIXED:
14212  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14213  return SCIP_INVALIDDATA;
14214 
14216  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14218  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14219  return SCIP_OKAY;
14220 
14222  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14223  return SCIP_INVALIDDATA;
14224 
14226  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14227  return SCIP_OKAY;
14228 
14229  default:
14230  SCIPerrorMessage("unknown variable status\n");
14231  return SCIP_INVALIDDATA;
14232  }
14233 }
14234 
14235 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14237  SCIP_VAR* var, /**< problem variable */
14238  SCIP_STAT* stat, /**< problem statistics */
14239  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14240  )
14241 {
14242  SCIP_BRANCHDIR dir;
14243 
14244  assert(var != NULL);
14245  assert(stat != NULL);
14246 
14247  switch( SCIPvarGetStatus(var) )
14248  {
14250  if( var->data.original.transvar == NULL )
14251  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14252  else
14253  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14254 
14255  case SCIP_VARSTATUS_LOOSE:
14256  case SCIP_VARSTATUS_COLUMN:
14257  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14258 
14259  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14260  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14261  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14262 
14263  case SCIP_VARSTATUS_FIXED:
14264  return 0.0;
14265 
14267  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14268 
14270  return 0.0;
14271 
14273  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14274 
14275  default:
14276  SCIPerrorMessage("unknown variable status\n");
14277  SCIPABORT();
14278  return 0.0; /*lint !e527*/
14279  }
14280 }
14281 
14282 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14283  * only using the pseudo cost information of the current run
14284  */
14286  SCIP_VAR* var, /**< problem variable */
14287  SCIP_STAT* stat, /**< problem statistics */
14288  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14289  )
14290 {
14291  SCIP_BRANCHDIR dir;
14292 
14293  assert(var != NULL);
14294  assert(stat != NULL);
14295 
14296  switch( SCIPvarGetStatus(var) )
14297  {
14299  if( var->data.original.transvar == NULL )
14300  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14301  else
14302  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14303 
14304  case SCIP_VARSTATUS_LOOSE:
14305  case SCIP_VARSTATUS_COLUMN:
14306  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14307 
14308  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14309  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14310  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14311 
14312  case SCIP_VARSTATUS_FIXED:
14313  return 0.0;
14314 
14316  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14317 
14319  return 0.0;
14320 
14322  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14323 
14324  default:
14325  SCIPerrorMessage("unknown variable status\n");
14326  SCIPABORT();
14327  return 0.0; /*lint !e527*/
14328  }
14329 }
14330 
14331 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14333  SCIP_VAR* var, /**< problem variable */
14334  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14335  )
14336 {
14337  assert(var != NULL);
14338  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14339 
14340  switch( SCIPvarGetStatus(var) )
14341  {
14343  if( var->data.original.transvar == NULL )
14344  return 0.0;
14345  else
14346  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14347 
14348  case SCIP_VARSTATUS_LOOSE:
14349  case SCIP_VARSTATUS_COLUMN:
14350  return SCIPhistoryGetPseudocostCount(var->history, dir);
14351 
14352  case SCIP_VARSTATUS_FIXED:
14353  return 0.0;
14354 
14356  if( var->data.aggregate.scalar > 0.0 )
14357  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14358  else
14360 
14362  return 0.0;
14363 
14366 
14367  default:
14368  SCIPerrorMessage("unknown variable status\n");
14369  SCIPABORT();
14370  return 0.0; /*lint !e527*/
14371  }
14372 }
14373 
14374 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14375  * only using the pseudo cost information of the current run
14376  */
14378  SCIP_VAR* var, /**< problem variable */
14379  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14380  )
14381 {
14382  assert(var != NULL);
14383  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14384 
14385  switch( SCIPvarGetStatus(var) )
14386  {
14388  if( var->data.original.transvar == NULL )
14389  return 0.0;
14390  else
14392 
14393  case SCIP_VARSTATUS_LOOSE:
14394  case SCIP_VARSTATUS_COLUMN:
14395  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14396 
14397  case SCIP_VARSTATUS_FIXED:
14398  return 0.0;
14399 
14401  if( var->data.aggregate.scalar > 0.0 )
14403  else
14405 
14407  return 0.0;
14408 
14411 
14412  default:
14413  SCIPerrorMessage("unknown variable status\n");
14414  SCIPABORT();
14415  return 0.0; /*lint !e527*/
14416  }
14417 }
14418 
14419 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14421  SCIP_VAR* var, /**< problem variable */
14422  SCIP_STAT* stat, /**< problem statistics */
14423  SCIP_SET* set, /**< global SCIP settings */
14424  SCIP_Real solval /**< solution value, e.g., LP solution value */
14425  )
14426 {
14427  SCIP_Real upscore;
14428  SCIP_Real downscore;
14429  SCIP_Real solvaldeltaup;
14430  SCIP_Real solvaldeltadown;
14431 
14432  /* LP root estimate only works for variables with fractional LP root solution */
14433  if( SCIPsetIsFeasIntegral(set, solval) )
14434  return 0.0;
14435 
14436  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14438  return 0.0;
14439 
14440  /* compute delta's to ceil and floor of root LP solution value */
14441  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14442  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14443 
14444  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14445  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14446 
14447  return MIN(upscore, downscore);
14448 }
14449 
14450 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14452  SCIP_VAR* var, /**< problem variable */
14453  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14454  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14455  )
14456 {
14457  assert(var != NULL);
14458  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14459 
14460  switch( SCIPvarGetStatus(var) )
14461  {
14463  if( var->data.original.transvar == NULL )
14464  return 0.0;
14465  else
14466  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14467 
14468  case SCIP_VARSTATUS_LOOSE:
14469  case SCIP_VARSTATUS_COLUMN:
14470  if( onlycurrentrun )
14472  else
14473  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14474 
14475  case SCIP_VARSTATUS_FIXED:
14476  return 0.0;
14477 
14479  if( var->data.aggregate.scalar > 0.0 )
14480  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14481  else
14482  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14483 
14485  return 0.0;
14486 
14488  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14489 
14490  default:
14491  SCIPerrorMessage("unknown variable status\n");
14492  SCIPABORT();
14493  return 0.0; /*lint !e527*/
14494  }
14495 }
14496 
14497 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14498  *
14499  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14500  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14501  * of 2 * clevel - 1.
14502  *
14503  * @return value of confidence bound for this variable
14504  */
14506  SCIP_VAR* var, /**< variable in question */
14507  SCIP_SET* set, /**< global SCIP settings */
14508  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14509  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14510  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14511  )
14512 {
14513  SCIP_Real confidencebound;
14514 
14515  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14516  if( SCIPsetIsFeasPositive(set, confidencebound) )
14517  {
14518  SCIP_Real count;
14519 
14520  if( onlycurrentrun )
14521  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14522  else
14523  count = SCIPvarGetPseudocostCount(var, dir);
14524  /* assertion is valid because variance is positive */
14525  assert(count >= 1.9);
14526 
14527  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14528  confidencebound = sqrt(confidencebound);
14529 
14530  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14531  * the number of pseudo cost evaluations of this variable in the respective direction. */
14532  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14533  }
14534  else
14535  confidencebound = 0.0;
14536 
14537  return confidencebound;
14538 }
14539 
14540 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14541  * Error is calculated at a specific confidence level
14542  */
14544  SCIP_VAR* var, /**< variable in question */
14545  SCIP_SET* set, /**< global SCIP settings */
14546  SCIP_STAT* stat, /**< problem statistics */
14547  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14548  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14549  )
14550 {
14551  SCIP_Real downsize;
14552  SCIP_Real upsize;
14553  SCIP_Real size;
14554  SCIP_Real relerrorup;
14555  SCIP_Real relerrordown;
14556  SCIP_Real relerror;
14557 
14558  /* check, if the pseudo cost score of the variable is reliable */
14561  size = MIN(downsize, upsize);
14562 
14563  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14564  if( size <= 1.9 )
14565  return FALSE;
14566 
14567  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14568  * confidence interval bound at confidence level of 95% for individual variable reliability.
14569  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14570  */
14571  if( downsize >= 1.9 )
14572  {
14573  SCIP_Real normval;
14574 
14575  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14576  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14577  normval = MAX(1.0, normval);
14578 
14579  relerrordown /= normval;
14580  }
14581  else
14582  relerrordown = 0.0;
14583 
14584  if( upsize >= 1.9 )
14585  {
14586  SCIP_Real normval;
14587 
14588  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14589  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14590  normval = MAX(1.0, normval);
14591  relerrorup /= normval;
14592  }
14593  else
14594  relerrorup = 0.0;
14595 
14596  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14597  relerror = MAX(relerrorup, relerrordown);
14598 
14599  return (relerror <= threshold);
14600 }
14601 
14602 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14603  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14604  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14605  * unknown location means of the underlying pseudo-cost distributions of x and y.
14606  *
14607  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14608  * better than x (despite the current information), meaning that y can be expected to yield branching
14609  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14610  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14611  * than y.
14612  *
14613  * @note The order of x and y matters for the one-sided hypothesis
14614  *
14615  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14616  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14617  *
14618  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14619  */
14621  SCIP_SET* set, /**< global SCIP settings */
14622  SCIP_STAT* stat, /**< problem statistics */
14623  SCIP_VAR* varx, /**< variable x */
14624  SCIP_Real fracx, /**< the fractionality of variable x */
14625  SCIP_VAR* vary, /**< variable y */
14626  SCIP_Real fracy, /**< the fractionality of variable y */
14627  SCIP_BRANCHDIR dir, /**< branching direction */
14628  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14629  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14630  )
14631 {
14632  SCIP_Real meanx;
14633  SCIP_Real meany;
14634  SCIP_Real variancex;
14635  SCIP_Real variancey;
14636  SCIP_Real countx;
14637  SCIP_Real county;
14638  SCIP_Real tresult;
14639  SCIP_Real realdirection;
14640 
14641  if( varx == vary )
14642  return FALSE;
14643 
14644  countx = SCIPvarGetPseudocostCount(varx, dir);
14645  county = SCIPvarGetPseudocostCount(vary, dir);
14646 
14647  /* if not at least 2 measurements were taken, return FALSE */
14648  if( countx <= 1.9 || county <= 1.9 )
14649  return FALSE;
14650 
14651  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14652 
14653  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14654  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14655 
14656  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14657  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14658 
14659  /* if there is no variance, the means are taken from a constant distribution */
14660  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14661  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14662 
14663  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14664 
14665  /* for the two-sided hypothesis, just take the absolute of t */
14666  if( !onesided )
14667  tresult = REALABS(tresult);
14668 
14669  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14670 }
14671 
14672 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14673  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14674  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14675  * of at least \p threshold.
14676  *
14677  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14678  * the estimated probability to exceed \p threshold is less than 25 %.
14679  *
14680  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14681  * of confidence.
14682  *
14683  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14684  * at the given confidence level \p clevel.
14685  */
14687  SCIP_SET* set, /**< global SCIP settings */
14688  SCIP_STAT* stat, /**< problem statistics */
14689  SCIP_VAR* var, /**< variable x */
14690  SCIP_Real frac, /**< the fractionality of variable x */
14691  SCIP_Real threshold, /**< the threshold to test against */
14692  SCIP_BRANCHDIR dir, /**< branching direction */
14693  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14694  )
14695 {
14696  SCIP_Real mean;
14697  SCIP_Real variance;
14698  SCIP_Real count;
14699  SCIP_Real realdirection;
14700  SCIP_Real probability;
14701  SCIP_Real problimit;
14702 
14703  count = SCIPvarGetPseudocostCount(var, dir);
14704 
14705  /* if not at least 2 measurements were taken, return FALSE */
14706  if( count <= 1.9 )
14707  return FALSE;
14708 
14709  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14710 
14711  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14712  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14713 
14714  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14715  if( SCIPsetIsFeasGE(set, mean, threshold) )
14716  return FALSE;
14717 
14718  /* if there is no variance, the means are taken from a constant distribution */
14719  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14720  return SCIPsetIsFeasLT(set, mean, threshold);
14721 
14722  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14723  probability = SCIPnormalCDF(mean, variance, threshold);
14724 
14725  /* determine a probability limit corresponding to the given confidence level */
14726  switch( clevel )
14727  {
14729  problimit = 0.75;
14730  break;
14732  problimit = 0.875;
14733  break;
14735  problimit = 0.9;
14736  break;
14738  problimit = 0.95;
14739  break;
14741  problimit = 0.975;
14742  break;
14743  default:
14744  problimit = -1;
14745  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14746  SCIPABORT();
14747  break;
14748  }
14749 
14750  return (probability >= problimit);
14751 }
14752 
14753 /** find the corresponding history entry if already existing, otherwise create new entry */
14754 static
14756  SCIP_VAR* var, /**< problem variable */
14757  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14758  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14759  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14760  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14761  )
14762 {
14763  assert(var != NULL);
14764  assert(blkmem != NULL);
14765  assert(set != NULL);
14766  assert(history != NULL);
14767 
14768  (*history) = NULL;
14769 
14770  if( var->valuehistory == NULL )
14771  {
14772  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14773  }
14774 
14775  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14776 
14777  return SCIP_OKAY;
14778 }
14779 
14780 /** check if value based history should be used */
14781 static
14783  SCIP_VAR* var, /**< problem variable */
14784  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14785  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14786  )
14787 {
14788  /* check if the domain value is unknown (not specific) */
14789  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14790  return FALSE;
14791 
14792  assert(set != NULL);
14793 
14794  /* check if value based history should be collected */
14795  if( !set->history_valuebased )
14796  return FALSE;
14797 
14798  /* value based history is not collected for binary variable since the standard history already contains all information */
14799  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14800  return FALSE;
14801 
14802  /* value based history is not collected for continuous variables */
14804  return FALSE;
14805 
14806  return TRUE;
14807 }
14808 
14809 /** increases VSIDS of the variable by the given weight */
14811  SCIP_VAR* var, /**< problem variable */
14812  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14813  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14814  SCIP_STAT* stat, /**< problem statistics */
14815  SCIP_BRANCHDIR dir, /**< branching direction */
14816  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14817  SCIP_Real weight /**< weight of this update in VSIDS */
14818  )
14819 {
14820  assert(var != NULL);
14821  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14822 
14823  /* check if history statistics should be collected for a variable */
14824  if( !stat->collectvarhistory )
14825  return SCIP_OKAY;
14826 
14827  if( SCIPsetIsZero(set, weight) )
14828  return SCIP_OKAY;
14829 
14830  switch( SCIPvarGetStatus(var) )
14831  {
14833  if( var->data.original.transvar == NULL )
14834  {
14835  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14836  return SCIP_INVALIDDATA;
14837  }
14838  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14839  return SCIP_OKAY;
14840 
14841  case SCIP_VARSTATUS_LOOSE:
14842  case SCIP_VARSTATUS_COLUMN:
14843  {
14844  SCIPhistoryIncVSIDS(var->history, dir, weight);
14845  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14846 
14847  if( useValuehistory(var, value, set) )
14848  {
14849  SCIP_HISTORY* history;
14850 
14851  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14852  assert(history != NULL);
14853 
14854  SCIPhistoryIncVSIDS(history, dir, weight);
14855  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14856  value, weight, SCIPhistoryGetVSIDS(history, dir));
14857  }
14858 
14859  return SCIP_OKAY;
14860  }
14861  case SCIP_VARSTATUS_FIXED:
14862  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14863  return SCIP_INVALIDDATA;
14864 
14866  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14867 
14868  if( var->data.aggregate.scalar > 0.0 )
14869  {
14870  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14871  }
14872  else
14873  {
14874  assert(var->data.aggregate.scalar < 0.0);
14875  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14876  }
14877  return SCIP_OKAY;
14878 
14880  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14881  return SCIP_INVALIDDATA;
14882 
14884  value = 1.0 - value;
14885 
14886  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14887  return SCIP_OKAY;
14888 
14889  default:
14890  SCIPerrorMessage("unknown variable status\n");
14891  return SCIP_INVALIDDATA;
14892  }
14893 }
14894 
14895 /** scales the VSIDS of the variable by the given scalar */
14897  SCIP_VAR* var, /**< problem variable */
14898  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14899  )
14900 {
14901  assert(var != NULL);
14902 
14903  switch( SCIPvarGetStatus(var) )
14904  {
14906  if( var->data.original.transvar == NULL )
14907  {
14908  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14909  return SCIP_INVALIDDATA;
14910  }
14912  return SCIP_OKAY;
14913 
14914  case SCIP_VARSTATUS_LOOSE:
14915  case SCIP_VARSTATUS_COLUMN:
14916  {
14917  SCIPhistoryScaleVSIDS(var->history, scalar);
14918  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14920 
14921  return SCIP_OKAY;
14922  }
14923  case SCIP_VARSTATUS_FIXED:
14924  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14925  return SCIP_INVALIDDATA;
14926 
14928  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14929  return SCIP_OKAY;
14930 
14932  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14933  return SCIP_INVALIDDATA;
14934 
14936  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14937  return SCIP_OKAY;
14938 
14939  default:
14940  SCIPerrorMessage("unknown variable status\n");
14941  return SCIP_INVALIDDATA;
14942  }
14943 }
14944 
14945 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14947  SCIP_VAR* var, /**< problem variable */
14948  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14949  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14950  SCIP_STAT* stat, /**< problem statistics */
14951  SCIP_BRANCHDIR dir, /**< branching direction */
14952  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14953  SCIP_Real length /**< length of the conflict */
14954  )
14955 {
14956  assert(var != NULL);
14957  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14958 
14959  /* check if history statistics should be collected for a variable */
14960  if( !stat->collectvarhistory )
14961  return SCIP_OKAY;
14962 
14963  switch( SCIPvarGetStatus(var) )
14964  {
14966  if( var->data.original.transvar == NULL )
14967  {
14968  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14969  return SCIP_INVALIDDATA;
14970  }
14971  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14972  return SCIP_OKAY;
14973 
14974  case SCIP_VARSTATUS_LOOSE:
14975  case SCIP_VARSTATUS_COLUMN:
14976  {
14977  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14978  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14979 
14980  if( useValuehistory(var, value, set) )
14981  {
14982  SCIP_HISTORY* history;
14983 
14984  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14985  assert(history != NULL);
14986 
14987  SCIPhistoryIncNActiveConflicts(history, dir, length);
14988  }
14989 
14990  return SCIP_OKAY;
14991  }
14992  case SCIP_VARSTATUS_FIXED:
14993  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14994  return SCIP_INVALIDDATA;
14995 
14997  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14998 
14999  if( var->data.aggregate.scalar > 0.0 )
15000  {
15001  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15002  }
15003  else
15004  {
15005  assert(var->data.aggregate.scalar < 0.0);
15006  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15007  }
15008  return SCIP_OKAY;
15009 
15011  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15012  return SCIP_INVALIDDATA;
15013 
15015  value = 1.0 - value;
15016 
15017  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15018  return SCIP_OKAY;
15019 
15020  default:
15021  SCIPerrorMessage("unknown variable status\n");
15022  return SCIP_INVALIDDATA;
15023  }
15024 }
15025 
15026 /** gets the number of active conflicts containing this variable in given direction */
15028  SCIP_VAR* var, /**< problem variable */
15029  SCIP_STAT* stat, /**< problem statistics */
15030  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15031  )
15032 {
15033  assert(var != NULL);
15034  assert(stat != NULL);
15035  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15036 
15037  switch( SCIPvarGetStatus(var) )
15038  {
15040  if( var->data.original.transvar == NULL )
15041  return 0;
15042  else
15043  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15044 
15045  case SCIP_VARSTATUS_LOOSE:
15046  case SCIP_VARSTATUS_COLUMN:
15047  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15048 
15049  case SCIP_VARSTATUS_FIXED:
15050  return 0;
15051 
15053  if( var->data.aggregate.scalar > 0.0 )
15054  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15055  else
15057 
15059  return 0;
15060 
15063 
15064  default:
15065  SCIPerrorMessage("unknown variable status\n");
15066  SCIPABORT();
15067  return 0; /*lint !e527*/
15068  }
15069 }
15070 
15071 /** gets the number of active conflicts containing this variable in given direction
15072  * in the current run
15073  */
15075  SCIP_VAR* var, /**< problem variable */
15076  SCIP_STAT* stat, /**< problem statistics */
15077  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15078  )
15079 {
15080  assert(var != NULL);
15081  assert(stat != NULL);
15082  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15083 
15084  switch( SCIPvarGetStatus(var) )
15085  {
15087  if( var->data.original.transvar == NULL )
15088  return 0;
15089  else
15091 
15092  case SCIP_VARSTATUS_LOOSE:
15093  case SCIP_VARSTATUS_COLUMN:
15094  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15095 
15096  case SCIP_VARSTATUS_FIXED:
15097  return 0;
15098 
15100  if( var->data.aggregate.scalar > 0.0 )
15101  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15102  else
15104 
15106  return 0;
15107 
15110 
15111  default:
15112  SCIPerrorMessage("unknown variable status\n");
15113  SCIPABORT();
15114  return 0; /*lint !e527*/
15115  }
15116 }
15117 
15118 /** gets the average conflict length in given direction due to branching on the variable */
15120  SCIP_VAR* var, /**< problem variable */
15121  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15122  )
15123 {
15124  assert(var != NULL);
15125  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15126 
15127  switch( SCIPvarGetStatus(var) )
15128  {
15130  if( var->data.original.transvar == NULL )
15131  return 0.0;
15132  else
15134 
15135  case SCIP_VARSTATUS_LOOSE:
15136  case SCIP_VARSTATUS_COLUMN:
15137  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15138  case SCIP_VARSTATUS_FIXED:
15139  return 0.0;
15140 
15142  if( var->data.aggregate.scalar > 0.0 )
15143  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15144  else
15146 
15148  return 0.0;
15149 
15152 
15153  default:
15154  SCIPerrorMessage("unknown variable status\n");
15155  SCIPABORT();
15156  return 0.0; /*lint !e527*/
15157  }
15158 }
15159 
15160 /** gets the average conflict length in given direction due to branching on the variable
15161  * in the current run
15162  */
15164  SCIP_VAR* var, /**< problem variable */
15165  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15166  )
15167 {
15168  assert(var != NULL);
15169  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15170 
15171  switch( SCIPvarGetStatus(var) )
15172  {
15174  if( var->data.original.transvar == NULL )
15175  return 0.0;
15176  else
15178 
15179  case SCIP_VARSTATUS_LOOSE:
15180  case SCIP_VARSTATUS_COLUMN:
15181  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15182 
15183  case SCIP_VARSTATUS_FIXED:
15184  return 0.0;
15185 
15187  if( var->data.aggregate.scalar > 0.0 )
15189  else
15191 
15193  return 0.0;
15194 
15197 
15198  default:
15199  SCIPerrorMessage("unknown variable status\n");
15200  SCIPABORT();
15201  return 0.0; /*lint !e527*/
15202  }
15203 }
15204 
15205 /** increases the number of branchings counter of the variable */
15207  SCIP_VAR* var, /**< problem variable */
15208  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15209  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15210  SCIP_STAT* stat, /**< problem statistics */
15211  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15212  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15213  int depth /**< depth at which the bound change took place */
15214  )
15215 {
15216  assert(var != NULL);
15217  assert(stat != NULL);
15218  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15219 
15220  /* check if history statistics should be collected for a variable */
15221  if( !stat->collectvarhistory )
15222  return SCIP_OKAY;
15223 
15224  switch( SCIPvarGetStatus(var) )
15225  {
15227  if( var->data.original.transvar == NULL )
15228  {
15229  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15230  return SCIP_INVALIDDATA;
15231  }
15232  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15233  return SCIP_OKAY;
15234 
15235  case SCIP_VARSTATUS_LOOSE:
15236  case SCIP_VARSTATUS_COLUMN:
15237  {
15238  SCIPhistoryIncNBranchings(var->history, dir, depth);
15239  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15240  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15241  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15242 
15243  if( useValuehistory(var, value, set) )
15244  {
15245  SCIP_HISTORY* history;
15246 
15247  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15248  assert(history != NULL);
15249 
15250  SCIPhistoryIncNBranchings(history, dir, depth);
15251  }
15252 
15253  return SCIP_OKAY;
15254  }
15255  case SCIP_VARSTATUS_FIXED:
15256  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15257  return SCIP_INVALIDDATA;
15258 
15260  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15261 
15262  if( var->data.aggregate.scalar > 0.0 )
15263  {
15264  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15265  }
15266  else
15267  {
15268  assert(var->data.aggregate.scalar < 0.0);
15269  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15270  }
15271  return SCIP_OKAY;
15272 
15274  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15275  return SCIP_INVALIDDATA;
15276 
15278  value = 1.0 - value;
15279 
15280  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15281  return SCIP_OKAY;
15282 
15283  default:
15284  SCIPerrorMessage("unknown variable status\n");
15285  return SCIP_INVALIDDATA;
15286  }
15287 }
15288 
15289 /** increases the inference sum of the variable by the given weight */
15291  SCIP_VAR* var, /**< problem variable */
15292  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15293  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15294  SCIP_STAT* stat, /**< problem statistics */
15295  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15296  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15297  SCIP_Real weight /**< weight of this update in inference score */
15298  )
15299 {
15300  assert(var != NULL);
15301  assert(stat != NULL);
15302  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15303 
15304  /* check if history statistics should be collected for a variable */
15305  if( !stat->collectvarhistory )
15306  return SCIP_OKAY;
15307 
15308  switch( SCIPvarGetStatus(var) )
15309  {
15311  if( var->data.original.transvar == NULL )
15312  {
15313  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15314  return SCIP_INVALIDDATA;
15315  }
15316  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15317  return SCIP_OKAY;
15318 
15319  case SCIP_VARSTATUS_LOOSE:
15320  case SCIP_VARSTATUS_COLUMN:
15321  {
15322  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15323  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15324  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15325  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15326 
15327  if( useValuehistory(var, value, set) )
15328  {
15329  SCIP_HISTORY* history;
15330 
15331  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15332  assert(history != NULL);
15333 
15334  SCIPhistoryIncInferenceSum(history, dir, weight);
15335  }
15336 
15337  return SCIP_OKAY;
15338  }
15339  case SCIP_VARSTATUS_FIXED:
15340  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15341  return SCIP_INVALIDDATA;
15342 
15344  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15345 
15346  if( var->data.aggregate.scalar > 0.0 )
15347  {
15348  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15349  }
15350  else
15351  {
15352  assert(var->data.aggregate.scalar < 0.0);
15353  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15354  }
15355  return SCIP_OKAY;
15356 
15358  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15359  return SCIP_INVALIDDATA;
15360 
15362  value = 1.0 - value;
15363 
15364  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15365  return SCIP_OKAY;
15366 
15367  default:
15368  SCIPerrorMessage("unknown variable status\n");
15369  return SCIP_INVALIDDATA;
15370  }
15371 }
15372 
15373 /** increases the cutoff sum of the variable by the given weight */
15375  SCIP_VAR* var, /**< problem variable */
15376  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15377  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15378  SCIP_STAT* stat, /**< problem statistics */
15379  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15380  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15381  SCIP_Real weight /**< weight of this update in cutoff score */
15382  )
15383 {
15384  assert(var != NULL);
15385  assert(stat != NULL);
15386  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15387 
15388  /* check if history statistics should be collected for a variable */
15389  if( !stat->collectvarhistory )
15390  return SCIP_OKAY;
15391 
15392  switch( SCIPvarGetStatus(var) )
15393  {
15395  if( var->data.original.transvar == NULL )
15396  {
15397  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15398  return SCIP_INVALIDDATA;
15399  }
15400  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15401  return SCIP_OKAY;
15402 
15403  case SCIP_VARSTATUS_LOOSE:
15404  case SCIP_VARSTATUS_COLUMN:
15405  {
15406  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15407  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15408  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15409  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15410 
15411  if( useValuehistory(var, value, set) )
15412  {
15413  SCIP_HISTORY* history;
15414 
15415  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15416  assert(history != NULL);
15417 
15418  SCIPhistoryIncCutoffSum(history, dir, weight);
15419  }
15420 
15421  return SCIP_OKAY;
15422  }
15423  case SCIP_VARSTATUS_FIXED:
15424  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15425  return SCIP_INVALIDDATA;
15426 
15428  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15429 
15430  if( var->data.aggregate.scalar > 0.0 )
15431  {
15432  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15433  }
15434  else
15435  {
15436  assert(var->data.aggregate.scalar < 0.0);
15437  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15438  }
15439  return SCIP_OKAY;
15440 
15442  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15443  return SCIP_INVALIDDATA;
15444 
15446  value = 1.0 - value;
15447 
15448  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15449  return SCIP_OKAY;
15450 
15451  default:
15452  SCIPerrorMessage("unknown variable status\n");
15453  return SCIP_INVALIDDATA;
15454  }
15455 }
15456 
15457 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15459  SCIP_VAR* var, /**< problem variable */
15460  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15461  )
15462 {
15463  assert(var != NULL);
15464  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15465 
15466  switch( SCIPvarGetStatus(var) )
15467  {
15469  if( var->data.original.transvar == NULL )
15470  return 0;
15471  else
15472  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15473 
15474  case SCIP_VARSTATUS_LOOSE:
15475  case SCIP_VARSTATUS_COLUMN:
15476  return SCIPhistoryGetNBranchings(var->history, dir);
15477 
15478  case SCIP_VARSTATUS_FIXED:
15479  return 0;
15480 
15482  if( var->data.aggregate.scalar > 0.0 )
15483  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15484  else
15486 
15488  return 0;
15489 
15492 
15493  default:
15494  SCIPerrorMessage("unknown variable status\n");
15495  SCIPABORT();
15496  return 0; /*lint !e527*/
15497  }
15498 }
15499 
15500 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15501  * in the current run
15502  */
15504  SCIP_VAR* var, /**< problem variable */
15505  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15506  )
15507 {
15508  assert(var != NULL);
15509  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15510 
15511  switch( SCIPvarGetStatus(var) )
15512  {
15514  if( var->data.original.transvar == NULL )
15515  return 0;
15516  else
15518 
15519  case SCIP_VARSTATUS_LOOSE:
15520  case SCIP_VARSTATUS_COLUMN:
15521  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15522 
15523  case SCIP_VARSTATUS_FIXED:
15524  return 0;
15525 
15527  if( var->data.aggregate.scalar > 0.0 )
15529  else
15531 
15533  return 0;
15534 
15537 
15538  default:
15539  SCIPerrorMessage("unknown variable status\n");
15540  SCIPABORT();
15541  return 0; /*lint !e527*/
15542  }
15543 }
15544 
15545 /** returns the average depth of bound changes in given direction due to branching on the variable */
15547  SCIP_VAR* var, /**< problem variable */
15548  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15549  )
15550 {
15551  assert(var != NULL);
15552  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15553 
15554  switch( SCIPvarGetStatus(var) )
15555  {
15557  if( var->data.original.transvar == NULL )
15558  return 0.0;
15559  else
15560  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15561 
15562  case SCIP_VARSTATUS_LOOSE:
15563  case SCIP_VARSTATUS_COLUMN:
15564  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15565 
15566  case SCIP_VARSTATUS_FIXED:
15567  return 0.0;
15568 
15570  if( var->data.aggregate.scalar > 0.0 )
15571  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15572  else
15574 
15576  return 0.0;
15577 
15580 
15581  default:
15582  SCIPerrorMessage("unknown variable status\n");
15583  SCIPABORT();
15584  return 0.0; /*lint !e527*/
15585  }
15586 }
15587 
15588 /** returns the average depth of bound changes in given direction due to branching on the variable
15589  * in the current run
15590  */
15592  SCIP_VAR* var, /**< problem variable */
15593  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15594  )
15595 {
15596  assert(var != NULL);
15597  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15598 
15599  switch( SCIPvarGetStatus(var) )
15600  {
15602  if( var->data.original.transvar == NULL )
15603  return 0.0;
15604  else
15606 
15607  case SCIP_VARSTATUS_LOOSE:
15608  case SCIP_VARSTATUS_COLUMN:
15609  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15610 
15611  case SCIP_VARSTATUS_FIXED:
15612  return 0.0;
15613 
15615  if( var->data.aggregate.scalar > 0.0 )
15617  else
15620 
15622  return 0.0;
15623 
15626  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15627 
15628  default:
15629  SCIPerrorMessage("unknown variable status\n");
15630  SCIPABORT();
15631  return 0.0; /*lint !e527*/
15632  }
15633 }
15634 
15635 /** returns the variable's VSIDS score */
15637  SCIP_VAR* var, /**< problem variable */
15638  SCIP_STAT* stat, /**< problem statistics */
15639  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15640  )
15641 {
15642  assert(var != NULL);
15643  assert(stat != NULL);
15644  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15645 
15647  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15648 
15649  switch( SCIPvarGetStatus(var) )
15650  {
15652  if( var->data.original.transvar == NULL )
15653  return 0.0;
15654  else
15655  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15656 
15657  case SCIP_VARSTATUS_LOOSE:
15658  case SCIP_VARSTATUS_COLUMN:
15659  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15660  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15661 
15662  case SCIP_VARSTATUS_FIXED:
15663  return 0.0;
15664 
15666  if( var->data.aggregate.scalar > 0.0 )
15667  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15668  else
15669  /* coverity[overrun-local] */
15670  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15671 
15673  return 0.0;
15674 
15676  /* coverity[overrun-local] */
15677  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15678 
15679  default:
15680  SCIPerrorMessage("unknown variable status\n");
15681  SCIPABORT();
15682  return 0.0; /*lint !e527*/
15683  }
15684 }
15685 
15686 /** returns the variable's VSIDS score only using conflicts of the current run */
15688  SCIP_VAR* var, /**< problem variable */
15689  SCIP_STAT* stat, /**< problem statistics */
15690  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15691  )
15692 {
15693  assert(var != NULL);
15694  assert(stat != NULL);
15695  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15696 
15697  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15698  {
15699  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15700  return SCIP_INVALID;
15701  }
15702 
15703  switch( SCIPvarGetStatus(var) )
15704  {
15706  if( var->data.original.transvar == NULL )
15707  return 0.0;
15708  else
15709  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15710 
15711  case SCIP_VARSTATUS_LOOSE:
15712  case SCIP_VARSTATUS_COLUMN:
15713  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15714 
15715  case SCIP_VARSTATUS_FIXED:
15716  return 0.0;
15717 
15719  if( var->data.aggregate.scalar > 0.0 )
15720  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15721  else
15723 
15725  return 0.0;
15726 
15729 
15730  default:
15731  SCIPerrorMessage("unknown variable status\n");
15732  SCIPABORT();
15733  return 0.0; /*lint !e527*/
15734  }
15735 }
15736 
15737 /** returns the number of inferences branching on this variable in given direction triggered */
15739  SCIP_VAR* var, /**< problem variable */
15740  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15741  )
15742 {
15743  assert(var != NULL);
15744  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15745 
15746  switch( SCIPvarGetStatus(var) )
15747  {
15749  if( var->data.original.transvar == NULL )
15750  return 0.0;
15751  else
15752  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15753 
15754  case SCIP_VARSTATUS_LOOSE:
15755  case SCIP_VARSTATUS_COLUMN:
15756  return SCIPhistoryGetInferenceSum(var->history, dir);
15757 
15758  case SCIP_VARSTATUS_FIXED:
15759  return 0.0;
15760 
15762  if( var->data.aggregate.scalar > 0.0 )
15763  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15764  else
15766 
15768  return 0.0;
15769 
15772 
15773  default:
15774  SCIPerrorMessage("unknown variable status\n");
15775  SCIPABORT();
15776  return 0.0; /*lint !e527*/
15777  }
15778 }
15779 
15780 /** returns the number of inferences branching on this variable in given direction triggered
15781  * in the current run
15782  */
15784  SCIP_VAR* var, /**< problem variable */
15785  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15786  )
15787 {
15788  assert(var != NULL);
15789  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15790 
15791  switch( SCIPvarGetStatus(var) )
15792  {
15794  if( var->data.original.transvar == NULL )
15795  return 0.0;
15796  else
15798 
15799  case SCIP_VARSTATUS_LOOSE:
15800  case SCIP_VARSTATUS_COLUMN:
15801  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15802 
15803  case SCIP_VARSTATUS_FIXED:
15804  return 0.0;
15805 
15807  if( var->data.aggregate.scalar > 0.0 )
15809  else
15811 
15813  return 0.0;
15814 
15817 
15818  default:
15819  SCIPerrorMessage("unknown variable status\n");
15820  SCIPABORT();
15821  return 0.0; /*lint !e527*/
15822  }
15823 }
15824 
15825 /** returns the average number of inferences found after branching on the variable in given direction */
15827  SCIP_VAR* var, /**< problem variable */
15828  SCIP_STAT* stat, /**< problem statistics */
15829  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15830  )
15831 {
15832  assert(var != NULL);
15833  assert(stat != NULL);
15834  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15835 
15836  switch( SCIPvarGetStatus(var) )
15837  {
15839  if( var->data.original.transvar == NULL )
15840  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15841  else
15842  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15843 
15844  case SCIP_VARSTATUS_LOOSE:
15845  case SCIP_VARSTATUS_COLUMN:
15846  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15847  return SCIPhistoryGetAvgInferences(var->history, dir);
15848  else
15849  {
15850  int nimpls;
15851  int ncliques;
15852 
15853  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15854  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15855  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15856  }
15857 
15858  case SCIP_VARSTATUS_FIXED:
15859  return 0.0;
15860 
15862  if( var->data.aggregate.scalar > 0.0 )
15863  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15864  else
15866 
15868  return 0.0;
15869 
15871  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15872 
15873  default:
15874  SCIPerrorMessage("unknown variable status\n");
15875  SCIPABORT();
15876  return 0.0; /*lint !e527*/
15877  }
15878 }
15879 
15880 /** returns the average number of inferences found after branching on the variable in given direction
15881  * in the current run
15882  */
15884  SCIP_VAR* var, /**< problem variable */
15885  SCIP_STAT* stat, /**< problem statistics */
15886  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15887  )
15888 {
15889  assert(var != NULL);
15890  assert(stat != NULL);
15891  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15892 
15893  switch( SCIPvarGetStatus(var) )
15894  {
15896  if( var->data.original.transvar == NULL )
15897  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15898  else
15899  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15900 
15901  case SCIP_VARSTATUS_LOOSE:
15902  case SCIP_VARSTATUS_COLUMN:
15903  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15904  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15905  else
15906  {
15907  int nimpls;
15908  int ncliques;
15909 
15910  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15911  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15912  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15913  }
15914 
15915  case SCIP_VARSTATUS_FIXED:
15916  return 0.0;
15917 
15919  if( var->data.aggregate.scalar > 0.0 )
15920  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15921  else
15923 
15925  return 0.0;
15926 
15929 
15930  default:
15931  SCIPerrorMessage("unknown variable status\n");
15932  SCIPABORT();
15933  return 0.0; /*lint !e527*/
15934  }
15935 }
15936 
15937 /** returns the number of cutoffs branching on this variable in given direction produced */
15939  SCIP_VAR* var, /**< problem variable */
15940  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15941  )
15942 {
15943  assert(var != NULL);
15944  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15945 
15946  switch( SCIPvarGetStatus(var) )
15947  {
15949  if( var->data.original.transvar == NULL )
15950  return 0;
15951  else
15952  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15953 
15954  case SCIP_VARSTATUS_LOOSE:
15955  case SCIP_VARSTATUS_COLUMN:
15956  return SCIPhistoryGetCutoffSum(var->history, dir);
15957 
15958  case SCIP_VARSTATUS_FIXED:
15959  return 0;
15960 
15962  if( var->data.aggregate.scalar > 0.0 )
15963  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15964  else
15966 
15968  return 0;
15969 
15972 
15973  default:
15974  SCIPerrorMessage("unknown variable status\n");
15975  SCIPABORT();
15976  return 0; /*lint !e527*/
15977  }
15978 }
15979 
15980 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15982  SCIP_VAR* var, /**< problem variable */
15983  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15984  )
15985 {
15986  assert(var != NULL);
15987  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15988 
15989  switch( SCIPvarGetStatus(var) )
15990  {
15992  if( var->data.original.transvar == NULL )
15993  return 0;
15994  else
15996 
15997  case SCIP_VARSTATUS_LOOSE:
15998  case SCIP_VARSTATUS_COLUMN:
15999  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16000 
16001  case SCIP_VARSTATUS_FIXED:
16002  return 0;
16003 
16005  if( var->data.aggregate.scalar > 0.0 )
16006  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16007  else
16009 
16011  return 0;
16012 
16015 
16016  default:
16017  SCIPerrorMessage("unknown variable status\n");
16018  SCIPABORT();
16019  return 0; /*lint !e527*/
16020  }
16021 }
16022 
16023 /** returns the average number of cutoffs found after branching on the variable in given direction */
16025  SCIP_VAR* var, /**< problem variable */
16026  SCIP_STAT* stat, /**< problem statistics */
16027  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16028  )
16029 {
16030  assert(var != NULL);
16031  assert(stat != NULL);
16032  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16033 
16034  switch( SCIPvarGetStatus(var) )
16035  {
16037  if( var->data.original.transvar == NULL )
16038  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16039  else
16040  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16041 
16042  case SCIP_VARSTATUS_LOOSE:
16043  case SCIP_VARSTATUS_COLUMN:
16044  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16045  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16046  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16047 
16048  case SCIP_VARSTATUS_FIXED:
16049  return 0.0;
16050 
16052  if( var->data.aggregate.scalar > 0.0 )
16053  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16054  else
16055  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16056 
16058  return 0.0;
16059 
16061  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16062 
16063  default:
16064  SCIPerrorMessage("unknown variable status\n");
16065  SCIPABORT();
16066  return 0.0; /*lint !e527*/
16067  }
16068 }
16069 
16070 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16072  SCIP_VAR* var, /**< problem variable */
16073  SCIP_STAT* stat, /**< problem statistics */
16074  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16075  )
16076 {
16077  assert(var != NULL);
16078  assert(stat != NULL);
16079  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16080 
16081  switch( SCIPvarGetStatus(var) )
16082  {
16084  if( var->data.original.transvar == NULL )
16085  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16086  else
16087  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16088 
16089  case SCIP_VARSTATUS_LOOSE:
16090  case SCIP_VARSTATUS_COLUMN:
16091  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16094 
16095  case SCIP_VARSTATUS_FIXED:
16096  return 0.0;
16097 
16099  if( var->data.aggregate.scalar > 0.0 )
16100  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16101  else
16103 
16105  return 0.0;
16106 
16109 
16110  default:
16111  SCIPerrorMessage("unknown variable status\n");
16112  SCIPABORT();
16113  return 0.0; /*lint !e527*/
16114  }
16115 }
16116 
16117 
16118 
16119 
16120 /*
16121  * information methods for bound changes
16122  */
16123 
16124 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16126  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16127  BMS_BLKMEM* blkmem, /**< block memory */
16128  SCIP_VAR* var, /**< active variable that changed the bounds */
16129  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16130  SCIP_Real oldbound, /**< old value for bound */
16131  SCIP_Real newbound /**< new value for bound */
16132  )
16133 {
16134  assert(bdchginfo != NULL);
16135 
16136  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16137  (*bdchginfo)->oldbound = oldbound;
16138  (*bdchginfo)->newbound = newbound;
16139  (*bdchginfo)->var = var;
16140  (*bdchginfo)->inferencedata.var = var;
16141  (*bdchginfo)->inferencedata.reason.prop = NULL;
16142  (*bdchginfo)->inferencedata.info = 0;
16143  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16144  (*bdchginfo)->bdchgidx.pos = -1;
16145  (*bdchginfo)->pos = 0;
16146  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16147  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16148  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16149  (*bdchginfo)->redundant = FALSE;
16150 
16151  return SCIP_OKAY;
16152 }
16153 
16154 /** frees a bound change information object */
16155 void SCIPbdchginfoFree(
16156  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16157  BMS_BLKMEM* blkmem /**< block memory */
16158  )
16159 {
16160  assert(bdchginfo != NULL);
16161 
16162  BMSfreeBlockMemory(blkmem, bdchginfo);
16163 }
16164 
16165 /** returns the bound change information for the last lower bound change on given active problem variable before or
16166  * after the bound change with the given index was applied;
16167  * returns NULL, if no change to the lower bound was applied up to this point of time
16168  */
16170  SCIP_VAR* var, /**< active problem variable */
16171  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16172  SCIP_Bool after /**< should the bound change with given index be included? */
16173  )
16174 {
16175  int i;
16176 
16177  assert(var != NULL);
16178  assert(SCIPvarIsActive(var));
16179 
16180  /* search the correct bound change information for the given bound change index */
16181  if( after )
16182  {
16183  for( i = var->nlbchginfos-1; i >= 0; --i )
16184  {
16185  assert(var->lbchginfos[i].var == var);
16187  assert(var->lbchginfos[i].pos == i);
16188 
16189  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16190  if( var->lbchginfos[i].redundant )
16191  return NULL;
16192  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16193 
16194  /* if we reached the bound change index, return the current bound change info */
16195  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16196  return &var->lbchginfos[i];
16197  }
16198  }
16199  else
16200  {
16201  for( i = var->nlbchginfos-1; i >= 0; --i )
16202  {
16203  assert(var->lbchginfos[i].var == var);
16205  assert(var->lbchginfos[i].pos == i);
16206 
16207  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16208  if( var->lbchginfos[i].redundant )
16209  return NULL;
16210  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16211 
16212  /* if we reached the bound change index, return the current bound change info */
16213  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16214  return &var->lbchginfos[i];
16215  }
16216  }
16217 
16218  return NULL;
16219 }
16220 
16221 /** returns the bound change information for the last upper bound change on given active problem variable before or
16222  * after the bound change with the given index was applied;
16223  * returns NULL, if no change to the upper bound was applied up to this point of time
16224  */
16226  SCIP_VAR* var, /**< active problem variable */
16227  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16228  SCIP_Bool after /**< should the bound change with given index be included? */
16229  )
16230 {
16231  int i;
16232 
16233  assert(var != NULL);
16234  assert(SCIPvarIsActive(var));
16235 
16236  /* search the correct bound change information for the given bound change index */
16237  if( after )
16238  {
16239  for( i = var->nubchginfos-1; i >= 0; --i )
16240  {
16241  assert(var->ubchginfos[i].var == var);
16243  assert(var->ubchginfos[i].pos == i);
16244 
16245  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16246  if( var->ubchginfos[i].redundant )
16247  return NULL;
16248  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16249 
16250  /* if we reached the bound change index, return the current bound change info */
16251  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16252  return &var->ubchginfos[i];
16253  }
16254  }
16255  else
16256  {
16257  for( i = var->nubchginfos-1; i >= 0; --i )
16258  {
16259  assert(var->ubchginfos[i].var == var);
16261  assert(var->ubchginfos[i].pos == i);
16262 
16263  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16264  if( var->ubchginfos[i].redundant )
16265  return NULL;
16266  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16267 
16268  /* if we reached the bound change index, return the current bound change info */
16269  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16270  return &var->ubchginfos[i];
16271  }
16272  }
16273 
16274  return NULL;
16275 }
16276 
16277 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16278  * before or after the bound change with the given index was applied;
16279  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16280  */
16282  SCIP_VAR* var, /**< active problem variable */
16283  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16284  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16285  SCIP_Bool after /**< should the bound change with given index be included? */
16286  )
16287 {
16288  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16289  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16290  else
16291  {
16292  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16293  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16294  }
16295 }
16296 
16297 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16298  * was applied
16299  *
16300  * @deprecated Please use SCIPgetVarLbAtIndex()
16301  */
16303  SCIP_VAR* var, /**< problem variable */
16304  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16305  SCIP_Bool after /**< should the bound change with given index be included? */
16306  )
16307 {
16308  SCIP_VARSTATUS varstatus;
16309  assert(var != NULL);
16310 
16311  varstatus = SCIPvarGetStatus(var);
16312 
16313  /* get bounds of attached variables */
16314  switch( varstatus )
16315  {
16317  assert(var->data.original.transvar != NULL);
16318  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16319 
16320  case SCIP_VARSTATUS_LOOSE:
16321  case SCIP_VARSTATUS_COLUMN:
16322  if( bdchgidx == NULL )
16323  return SCIPvarGetLbLocal(var);
16324  else
16325  {
16326  SCIP_BDCHGINFO* bdchginfo;
16327 
16328  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16329  if( bdchginfo != NULL )
16330  return SCIPbdchginfoGetNewbound(bdchginfo);
16331  else
16332  return var->glbdom.lb;
16333  }
16334  case SCIP_VARSTATUS_FIXED:
16335  return var->glbdom.lb;
16336 
16337  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16338  assert(var->data.aggregate.var != NULL);
16339  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16340  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16341  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16342  * (or is called by) a public interface method; instead, we only assert that values are finite
16343  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16344  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16345  */
16346  if( var->data.aggregate.scalar > 0.0 )
16347  {
16348  /* a > 0 -> get lower bound of y */
16349  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16350  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16351  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16352  + var->data.aggregate.constant;
16353  }
16354  else if( var->data.aggregate.scalar < 0.0 )
16355  {
16356  /* a < 0 -> get upper bound of y */
16357  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16358  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16359  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16360  + var->data.aggregate.constant;
16361  }
16362  else
16363  {
16364  SCIPerrorMessage("scalar is zero in aggregation\n");
16365  SCIPABORT();
16366  return SCIP_INVALID; /*lint !e527*/
16367  }
16368 
16370  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16371  if ( var->data.multaggr.nvars == 1 )
16372  {
16373  assert(var->data.multaggr.vars != NULL);
16374  assert(var->data.multaggr.scalars != NULL);
16375  assert(var->data.multaggr.vars[0] != NULL);
16376 
16377  if( var->data.multaggr.scalars[0] > 0.0 )
16378  {
16379  /* a > 0 -> get lower bound of y */
16380  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16381  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16382  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16383  + var->data.multaggr.constant;
16384  }
16385  else if( var->data.multaggr.scalars[0] < 0.0 )
16386  {
16387  /* a < 0 -> get upper bound of y */
16388  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16389  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16390  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16391  + var->data.multaggr.constant;
16392  }
16393  else
16394  {
16395  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16396  SCIPABORT();
16397  return SCIP_INVALID; /*lint !e527*/
16398  }
16399  }
16400  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16401  SCIPABORT();
16402  return SCIP_INVALID; /*lint !e527*/
16403 
16404  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16405  assert(var->negatedvar != NULL);
16407  assert(var->negatedvar->negatedvar == var);
16408  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16409  default:
16410  SCIPerrorMessage("unknown variable status\n");
16411  SCIPABORT();
16412  return SCIP_INVALID; /*lint !e527*/
16413  }
16414 }
16415 
16416 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16417  * was applied
16418  *
16419  * @deprecated Please use SCIPgetVarUbAtIndex()
16420  */
16422  SCIP_VAR* var, /**< problem variable */
16423  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16424  SCIP_Bool after /**< should the bound change with given index be included? */
16425  )
16426 {
16427  SCIP_VARSTATUS varstatus;
16428  assert(var != NULL);
16429 
16430  varstatus = SCIPvarGetStatus(var);
16431 
16432  /* get bounds of attached variables */
16433  switch( varstatus )
16434  {
16436  assert(var->data.original.transvar != NULL);
16437  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16438 
16439  case SCIP_VARSTATUS_COLUMN:
16440  case SCIP_VARSTATUS_LOOSE:
16441  if( bdchgidx == NULL )
16442  return SCIPvarGetUbLocal(var);
16443  else
16444  {
16445  SCIP_BDCHGINFO* bdchginfo;
16446 
16447  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16448  if( bdchginfo != NULL )
16449  return SCIPbdchginfoGetNewbound(bdchginfo);
16450  else
16451  return var->glbdom.ub;
16452  }
16453 
16454  case SCIP_VARSTATUS_FIXED:
16455  return var->glbdom.ub;
16456 
16457  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16458  assert(var->data.aggregate.var != NULL);
16459  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16460  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16461  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16462  * (or is called by) a public interface method; instead, we only assert that values are finite
16463  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16464  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16465  */
16466  if( var->data.aggregate.scalar > 0.0 )
16467  {
16468  /* a > 0 -> get lower bound of y */
16469  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16470  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16471  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16472  + var->data.aggregate.constant;
16473  }
16474  else if( var->data.aggregate.scalar < 0.0 )
16475  {
16476  /* a < 0 -> get upper bound of y */
16477  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16478  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16479  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16480  + var->data.aggregate.constant;
16481  }
16482  else
16483  {
16484  SCIPerrorMessage("scalar is zero in aggregation\n");
16485  SCIPABORT();
16486  return SCIP_INVALID; /*lint !e527*/
16487  }
16488 
16490  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16491  if ( var->data.multaggr.nvars == 1 )
16492  {
16493  assert(var->data.multaggr.vars != NULL);
16494  assert(var->data.multaggr.scalars != NULL);
16495  assert(var->data.multaggr.vars[0] != NULL);
16496 
16497  if( var->data.multaggr.scalars[0] > 0.0 )
16498  {
16499  /* a > 0 -> get lower bound of y */
16500  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16501  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16502  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16503  + var->data.multaggr.constant;
16504  }
16505  else if( var->data.multaggr.scalars[0] < 0.0 )
16506  {
16507  /* a < 0 -> get upper bound of y */
16508  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16509  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16510  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16511  + var->data.multaggr.constant;
16512  }
16513  else
16514  {
16515  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16516  SCIPABORT();
16517  return SCIP_INVALID; /*lint !e527*/
16518  }
16519  }
16520  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16521  SCIPABORT();
16522  return SCIP_INVALID; /*lint !e527*/
16523 
16524  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16525  assert(var->negatedvar != NULL);
16527  assert(var->negatedvar->negatedvar == var);
16528  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16529 
16530  default:
16531  SCIPerrorMessage("unknown variable status\n");
16532  SCIPABORT();
16533  return SCIP_INVALID; /*lint !e527*/
16534  }
16535 }
16536 
16537 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16538  * was applied
16539  *
16540  * @deprecated Please use SCIPgetVarBdAtIndex()
16541  */
16543  SCIP_VAR* var, /**< problem variable */
16544  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16545  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16546  SCIP_Bool after /**< should the bound change with given index be included? */
16547  )
16548 {
16549  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16550  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16551  else
16552  {
16553  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16554  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16555  }
16556 }
16557 
16558 /** returns whether the binary variable was fixed at the time given by the bound change index
16559  *
16560  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16561  */
16563  SCIP_VAR* var, /**< problem variable */
16564  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16565  SCIP_Bool after /**< should the bound change with given index be included? */
16566  )
16567 {
16568  assert(var != NULL);
16569  assert(SCIPvarIsBinary(var));
16570 
16571  /* check the current bounds first in order to decide at which bound change information we have to look
16572  * (which is expensive because we have to follow the aggregation tree to the active variable)
16573  */
16574  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16575  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16576 }
16577 
16578 /** bound change index representing the initial time before any bound changes took place */
16579 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16581 /** bound change index representing the presolving stage */
16582 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16584 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16586  SCIP_VAR* var /**< problem variable */
16587  )
16588 {
16589  SCIP_BDCHGIDX* lbchgidx;
16590  SCIP_BDCHGIDX* ubchgidx;
16591 
16592  assert(var != NULL);
16593 
16594  var = SCIPvarGetProbvar(var);
16595 
16596  /* check, if variable is original without transformed variable */
16597  if( var == NULL )
16598  return &initbdchgidx;
16599 
16600  /* check, if variable was fixed in presolving */
16601  if( !SCIPvarIsActive(var) )
16602  return &presolvebdchgidx;
16603 
16605 
16606  /* get depths of last bound change information for the lower and upper bound */
16607  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16608  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16609  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16610  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16611 
16612  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16613  return ubchgidx;
16614  else
16615  return lbchgidx;
16616 }
16617 
16618 /** returns the last depth level, at which the bounds of the given variable were tightened;
16619  * returns -2, if the variable's bounds are still the global bounds
16620  * returns -1, if the variable was fixed in presolving
16621  */
16623  SCIP_VAR* var /**< problem variable */
16624  )
16625 {
16626  SCIP_BDCHGIDX* bdchgidx;
16627 
16628  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16629  assert(bdchgidx != NULL);
16630 
16631  return bdchgidx->depth;
16632 }
16633 
16634 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16635  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16636  */
16638  SCIP_VAR* var, /**< problem variable */
16639  SCIP_SET* set, /**< global SCIP settings */
16640  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16641  SCIP_Real bound /**< conflicting bound */
16642  )
16643 {
16644  int i;
16645 
16646  assert(var != NULL);
16647  assert(set != NULL);
16648  assert(var->scip == set->scip);
16649 
16650  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16651  {
16652  /* check if the bound is in conflict with the current local bounds */
16653  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16654  return -1;
16655 
16656  /* check if the bound is in conflict with the global bound */
16657  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16658  return 0;
16659 
16660  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16661  assert(var->nubchginfos > 0);
16662  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16663 
16664  /* search for the first conflicting bound change */
16665  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16666  {
16667  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16669  }
16670  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16671  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16672 
16673  /* return the depth at which the first conflicting bound change took place */
16674  return var->ubchginfos[i].bdchgidx.depth;
16675  }
16676  else
16677  {
16678  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16679 
16680  /* check if the bound is in conflict with the current local bounds */
16681  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16682  return -1;
16683 
16684  /* check if the bound is in conflict with the global bound */
16685  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16686  return 0;
16687 
16688  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16689  assert(var->nlbchginfos > 0);
16690  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16691 
16692  /* search for the first conflicting bound change */
16693  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16694  {
16695  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16697  }
16698  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16699  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16700 
16701  /* return the depth at which the first conflicting bound change took place */
16702  return var->lbchginfos[i].bdchgidx.depth;
16703  }
16704 }
16705 
16706 /** returns whether the first binary variable was fixed earlier than the second one;
16707  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16708  * second one is not fixed
16709  */
16711  SCIP_VAR* var1, /**< first binary variable */
16712  SCIP_VAR* var2 /**< second binary variable */
16713  )
16714 {
16715  SCIP_BDCHGIDX* bdchgidx1;
16716  SCIP_BDCHGIDX* bdchgidx2;
16717 
16718  assert(var1 != NULL);
16719  assert(var2 != NULL);
16720  assert(SCIPvarIsBinary(var1));
16721  assert(SCIPvarIsBinary(var2));
16722 
16723  var1 = SCIPvarGetProbvar(var1);
16724  var2 = SCIPvarGetProbvar(var2);
16725  assert(var1 != NULL);
16726  assert(var2 != NULL);
16727 
16728  /* check, if variables are globally fixed */
16729  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16730  return FALSE;
16731  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16732  return TRUE;
16733 
16736  assert(SCIPvarIsBinary(var1));
16737  assert(SCIPvarIsBinary(var2));
16738  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16739  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16740  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16741  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16742  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16743  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16744 
16745  if( var1->nlbchginfos == 1 )
16746  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16747  else if( var1->nubchginfos == 1 )
16748  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16749  else
16750  bdchgidx1 = NULL;
16751 
16752  if( var2->nlbchginfos == 1 )
16753  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16754  else if( var2->nubchginfos == 1 )
16755  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16756  else
16757  bdchgidx2 = NULL;
16758 
16759  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16760 }
16761 
16762 
16763 
16764 /*
16765  * Hash functions
16766  */
16767 
16768 /** gets the key (i.e. the name) of the given variable */
16769 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16770 { /*lint --e{715}*/
16771  SCIP_VAR* var = (SCIP_VAR*)elem;
16772 
16773  assert(var != NULL);
16774  return var->name;
16775 }
16776 
16777 
16778 
16779 
16780 /*
16781  * simple functions implemented as defines
16782  */
16783 
16784 /* In debug mode, the following methods are implemented as function calls to ensure
16785  * type validity.
16786  * In optimized mode, the methods are implemented as defines to improve performance.
16787  * However, we want to have them in the library anyways, so we have to undef the defines.
16788  */
16789 
16790 #undef SCIPboundchgGetNewbound
16791 #undef SCIPboundchgGetVar
16792 #undef SCIPboundchgGetBoundchgtype
16793 #undef SCIPboundchgGetBoundtype
16794 #undef SCIPboundchgIsRedundant
16795 #undef SCIPdomchgGetNBoundchgs
16796 #undef SCIPdomchgGetBoundchg
16797 #undef SCIPholelistGetLeft
16798 #undef SCIPholelistGetRight
16799 #undef SCIPholelistGetNext
16800 #undef SCIPvarGetName
16801 #undef SCIPvarGetNUses
16802 #undef SCIPvarGetData
16803 #undef SCIPvarSetData
16804 #undef SCIPvarSetDelorigData
16805 #undef SCIPvarSetTransData
16806 #undef SCIPvarSetDeltransData
16807 #undef SCIPvarGetStatus
16808 #undef SCIPvarIsOriginal
16809 #undef SCIPvarIsTransformed
16810 #undef SCIPvarIsNegated
16811 #undef SCIPvarGetType
16812 #undef SCIPvarIsBinary
16813 #undef SCIPvarIsIntegral
16814 #undef SCIPvarIsInitial
16815 #undef SCIPvarIsRemovable
16816 #undef SCIPvarIsDeleted
16817 #undef SCIPvarIsDeletable
16818 #undef SCIPvarMarkDeletable
16819 #undef SCIPvarMarkNotDeletable
16820 #undef SCIPvarIsActive
16821 #undef SCIPvarGetIndex
16822 #undef SCIPvarGetProbindex
16823 #undef SCIPvarGetTransVar
16824 #undef SCIPvarGetCol
16825 #undef SCIPvarIsInLP
16826 #undef SCIPvarGetAggrVar
16827 #undef SCIPvarGetAggrScalar
16828 #undef SCIPvarGetAggrConstant
16829 #undef SCIPvarGetMultaggrNVars
16830 #undef SCIPvarGetMultaggrVars
16831 #undef SCIPvarGetMultaggrScalars
16832 #undef SCIPvarGetMultaggrConstant
16833 #undef SCIPvarGetNegatedVar
16834 #undef SCIPvarGetNegationVar
16835 #undef SCIPvarGetNegationConstant
16836 #undef SCIPvarGetObj
16837 #undef SCIPvarGetLbOriginal
16838 #undef SCIPvarGetUbOriginal
16839 #undef SCIPvarGetHolelistOriginal
16840 #undef SCIPvarGetLbGlobal
16841 #undef SCIPvarGetUbGlobal
16842 #undef SCIPvarGetHolelistGlobal
16843 #undef SCIPvarGetBestBoundGlobal
16844 #undef SCIPvarGetWorstBoundGlobal
16845 #undef SCIPvarGetLbLocal
16846 #undef SCIPvarGetUbLocal
16847 #undef SCIPvarGetHolelistLocal
16848 #undef SCIPvarGetBestBoundLocal
16849 #undef SCIPvarGetWorstBoundLocal
16850 #undef SCIPvarGetBestBoundType
16851 #undef SCIPvarGetWorstBoundType
16852 #undef SCIPvarGetLbLazy
16853 #undef SCIPvarGetUbLazy
16854 #undef SCIPvarGetBranchFactor
16855 #undef SCIPvarGetBranchPriority
16856 #undef SCIPvarGetBranchDirection
16857 #undef SCIPvarGetNVlbs
16858 #undef SCIPvarGetVlbVars
16859 #undef SCIPvarGetVlbCoefs
16860 #undef SCIPvarGetVlbConstants
16861 #undef SCIPvarGetNVubs
16862 #undef SCIPvarGetVubVars
16863 #undef SCIPvarGetVubCoefs
16864 #undef SCIPvarGetVubConstants
16865 #undef SCIPvarGetNImpls
16866 #undef SCIPvarGetImplVars
16867 #undef SCIPvarGetImplTypes
16868 #undef SCIPvarGetImplBounds
16869 #undef SCIPvarGetImplIds
16870 #undef SCIPvarGetNCliques
16871 #undef SCIPvarGetCliques
16872 #undef SCIPvarGetLPSol
16873 #undef SCIPvarGetNLPSol
16874 #undef SCIPvarGetBdchgInfoLb
16875 #undef SCIPvarGetNBdchgInfosLb
16876 #undef SCIPvarGetBdchgInfoUb
16877 #undef SCIPvarGetNBdchgInfosUb
16878 #undef SCIPvarGetValuehistory
16879 #undef SCIPvarGetPseudoSol
16880 #undef SCIPvarCatchEvent
16881 #undef SCIPvarDropEvent
16882 #undef SCIPvarGetVSIDS
16883 #undef SCIPvarGetCliqueComponentIdx
16884 #undef SCIPvarIsRelaxationOnly
16885 #undef SCIPvarMarkRelaxationOnly
16886 #undef SCIPbdchgidxGetPos
16887 #undef SCIPbdchgidxIsEarlierNonNull
16888 #undef SCIPbdchgidxIsEarlier
16889 #undef SCIPbdchginfoGetOldbound
16890 #undef SCIPbdchginfoGetNewbound
16891 #undef SCIPbdchginfoGetVar
16892 #undef SCIPbdchginfoGetChgtype
16893 #undef SCIPbdchginfoGetBoundtype
16894 #undef SCIPbdchginfoGetDepth
16895 #undef SCIPbdchginfoGetPos
16896 #undef SCIPbdchginfoGetIdx
16897 #undef SCIPbdchginfoGetInferVar
16898 #undef SCIPbdchginfoGetInferCons
16899 #undef SCIPbdchginfoGetInferProp
16900 #undef SCIPbdchginfoGetInferInfo
16901 #undef SCIPbdchginfoGetInferBoundtype
16902 #undef SCIPbdchginfoIsRedundant
16903 #undef SCIPbdchginfoHasInferenceReason
16904 #undef SCIPbdchginfoIsTighter
16905 
16906 
16907 /** returns the new value of the bound in the bound change data */
16909  SCIP_BOUNDCHG* boundchg /**< bound change data */
16910  )
16911 {
16912  assert(boundchg != NULL);
16913 
16914  return boundchg->newbound;
16915 }
16916 
16917 /** returns the variable of the bound change in the bound change data */
16919  SCIP_BOUNDCHG* boundchg /**< bound change data */
16920  )
16921 {
16922  assert(boundchg != NULL);
16923 
16924  return boundchg->var;
16925 }
16926 
16927 /** returns the bound change type of the bound change in the bound change data */
16929  SCIP_BOUNDCHG* boundchg /**< bound change data */
16930  )
16931 {
16932  assert(boundchg != NULL);
16933 
16934  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16935 }
16936 
16937 /** returns the bound type of the bound change in the bound change data */
16939  SCIP_BOUNDCHG* boundchg /**< bound change data */
16940  )
16941 {
16942  assert(boundchg != NULL);
16943 
16944  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16945 }
16946 
16947 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16949  SCIP_BOUNDCHG* boundchg /**< bound change data */
16950  )
16951 {
16952  assert(boundchg != NULL);
16953 
16954  return boundchg->redundant;
16955 }
16956 
16957 /** returns the number of bound changes in the domain change data */
16959  SCIP_DOMCHG* domchg /**< domain change data */
16960  )
16961 {
16962  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16963 }
16964 
16965 /** returns a particular bound change in the domain change data */
16967  SCIP_DOMCHG* domchg, /**< domain change data */
16968  int pos /**< position of the bound change in the domain change data */
16969  )
16970 {
16971  assert(domchg != NULL);
16972  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16973 
16974  return &domchg->domchgbound.boundchgs[pos];
16975 }
16976 
16977 /** returns left bound of open interval in hole */
16979  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16980  )
16981 {
16982  assert(holelist != NULL);
16983 
16984  return holelist->hole.left;
16985 }
16986 
16987 /** returns right bound of open interval in hole */
16989  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16990  )
16991 {
16992  assert(holelist != NULL);
16993 
16994  return holelist->hole.right;
16995 }
16996 
16997 /** returns next hole in list */
16999  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17000  )
17001 {
17002  assert(holelist != NULL);
17003 
17004  return holelist->next;
17005 }
17006 
17007 /** returns the name of the variable
17008  *
17009  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17010  */
17011 const char* SCIPvarGetName(
17012  SCIP_VAR* var /**< problem variable */
17013  )
17014 {
17015  assert(var != NULL);
17016 
17017  return var->name;
17018 }
17019 
17020 /** gets number of times, the variable is currently captured */
17021 int SCIPvarGetNUses(
17022  SCIP_VAR* var /**< problem variable */
17023  )
17024 {
17025  assert(var != NULL);
17026 
17027  return var->nuses;
17028 }
17029 
17030 /** returns the user data of the variable */
17032  SCIP_VAR* var /**< problem variable */
17033  )
17034 {
17035  assert(var != NULL);
17036 
17037  return var->vardata;
17038 }
17039 
17040 /** sets the user data for the variable */
17041 void SCIPvarSetData(
17042  SCIP_VAR* var, /**< problem variable */
17043  SCIP_VARDATA* vardata /**< user variable data */
17044  )
17045 {
17046  assert(var != NULL);
17047 
17048  var->vardata = vardata;
17049 }
17050 
17051 /** sets method to free user data for the original variable */
17053  SCIP_VAR* var, /**< problem variable */
17054  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17055  )
17056 {
17057  assert(var != NULL);
17058  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17059 
17060  var->vardelorig = vardelorig;
17061 }
17062 
17063 /** sets method to transform user data of the variable */
17064 void SCIPvarSetTransData(
17065  SCIP_VAR* var, /**< problem variable */
17066  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17067  )
17068 {
17069  assert(var != NULL);
17070  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17071 
17072  var->vartrans = vartrans;
17073 }
17074 
17075 /** sets method to free transformed user data for the variable */
17077  SCIP_VAR* var, /**< problem variable */
17078  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17079  )
17080 {
17081  assert(var != NULL);
17082 
17083  var->vardeltrans = vardeltrans;
17084 }
17085 
17086 /** sets method to copy this variable into sub-SCIPs */
17087 void SCIPvarSetCopyData(
17088  SCIP_VAR* var, /**< problem variable */
17089  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17090  )
17091 {
17092  assert(var != NULL);
17093 
17094  var->varcopy = varcopy;
17095 }
17096 
17097 /** sets the initial flag of a variable; only possible for original or loose variables */
17099  SCIP_VAR* var, /**< problem variable */
17100  SCIP_Bool initial /**< initial flag */
17101  )
17102 {
17103  assert(var != NULL);
17104 
17106  return SCIP_INVALIDCALL;
17107 
17108  var->initial = initial;
17109 
17110  return SCIP_OKAY;
17111 }
17112 
17113 /** sets the removable flag of a variable; only possible for original or loose variables */
17115  SCIP_VAR* var, /**< problem variable */
17116  SCIP_Bool removable /**< removable flag */
17117  )
17118 {
17119  assert(var != NULL);
17120 
17122  return SCIP_INVALIDCALL;
17123 
17124  var->removable = removable;
17125 
17126  return SCIP_OKAY;
17127 }
17128 
17129 /** gets status of variable */
17131  SCIP_VAR* var /**< problem variable */
17132  )
17133 {
17134  assert(var != NULL);
17135 
17136  return (SCIP_VARSTATUS)(var->varstatus);
17137 }
17138 
17139 /** returns whether the variable belongs to the original problem */
17141  SCIP_VAR* var /**< problem variable */
17142  )
17143 {
17144  assert(var != NULL);
17145  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17146 
17150 }
17151 
17152 /** returns whether the variable belongs to the transformed problem */
17154  SCIP_VAR* var /**< problem variable */
17155  )
17156 {
17157  assert(var != NULL);
17158  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17159 
17163 }
17164 
17165 /** returns whether the variable was created by negation of a different variable */
17167  SCIP_VAR* var /**< problem variable */
17168  )
17169 {
17170  assert(var != NULL);
17171 
17172  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17173 }
17174 
17175 /** gets type of variable */
17177  SCIP_VAR* var /**< problem variable */
17178  )
17179 {
17180  assert(var != NULL);
17181 
17182  return (SCIP_VARTYPE)(var->vartype);
17183 }
17184 
17185 /** returns TRUE if the variable is of binary type; this is the case if:
17186  * (1) variable type is binary
17187  * (2) variable type is integer or implicit integer and
17188  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
17189  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
17190  */
17192  SCIP_VAR* var /**< problem variable */
17193  )
17194 {
17195  assert(var != NULL);
17196 
17197  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17198  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
17199 }
17200 
17201 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17203  SCIP_VAR* var /**< problem variable */
17204  )
17205 {
17206  assert(var != NULL);
17207 
17208  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17209 }
17210 
17211 /** returns whether variable's column should be present in the initial root LP */
17213  SCIP_VAR* var /**< problem variable */
17214  )
17215 {
17216  assert(var != NULL);
17217 
17218  return var->initial;
17219 }
17220 
17221 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17223  SCIP_VAR* var /**< problem variable */
17224  )
17225 {
17226  assert(var != NULL);
17227 
17228  return var->removable;
17229 }
17230 
17231 /** returns whether the variable was deleted from the problem */
17233  SCIP_VAR* var /**< problem variable */
17234  )
17235 {
17236  assert(var != NULL);
17237 
17238  return var->deleted;
17239 }
17240 
17241 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17242  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17243  */
17245  SCIP_VAR* var /**< problem variable */
17246  )
17247 {
17248  assert(var != NULL);
17249  assert(var->probindex == -1);
17250 
17251  var->deletable = TRUE;
17252 }
17253 
17254 /** marks the variable to be not deletable from the problem */
17257  )
17258 {
17259  assert(var != NULL);
17260 
17261  var->deletable = FALSE;
17262 }
17263 
17264 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17265  *
17266  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17267  */
17269  SCIP_VAR* var /**< problem variable */
17270  )
17271 {
17272  assert(var != NULL);
17273 
17274  var->delglobalstructs = TRUE;
17275 }
17276 
17277 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17279  SCIP_VAR* var /**< problem variable */
17280  )
17281 {
17282  assert(var != NULL);
17283 
17284  return var->delglobalstructs;
17285 }
17286 
17287 /** returns whether a variable has been introduced to define a relaxation
17288  *
17289  * These variables are only valid for the current SCIP solve round,
17290  * they are not contained in any (checked) constraints, but may be used
17291  * in cutting planes, for example.
17292  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17293  * that contain these variables are not added as linear constraints when
17294  * restarting or transferring information from a copied SCIP to a SCIP.
17295  * Also conflicts with relaxation-only variables are not generated at
17296  * the moment.
17297  */
17299  SCIP_VAR* var /**< problem variable */
17300  )
17301 {
17302  assert(var != NULL);
17303 
17304  return var->relaxationonly;
17305 }
17306 
17307 /** marks that this variable has only been introduced to define a relaxation
17308  *
17309  * The variable must not have a coefficient in the objective.
17310  *
17311  * @see SCIPvarIsRelaxationOnly
17312  */
17314  SCIP_VAR* var /**< problem variable */
17315  )
17316 {
17317  assert(var != NULL);
17318  assert(SCIPvarGetObj(var) == 0.0);
17319 
17320  var->relaxationonly = TRUE;
17321 }
17322 
17323 /** returns whether variable is allowed to be deleted completely from the problem */
17326  )
17327 {
17328  assert(var != NULL);
17329 
17330  return var->deletable;
17331 }
17332 
17333 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17335  SCIP_VAR* var /**< problem variable */
17336  )
17337 {
17338  assert(var != NULL);
17339 
17340  return (var->probindex >= 0);
17341 }
17342 
17343 /** gets unique index of variable */
17344 int SCIPvarGetIndex(
17345  SCIP_VAR* var /**< problem variable */
17346  )
17347 {
17348  assert(var != NULL);
17349 
17350  return var->index;
17351 }
17352 
17353 /** gets position of variable in problem, or -1 if variable is not active */
17355  SCIP_VAR* var /**< problem variable */
17356  )
17357 {
17358  assert(var != NULL);
17359 
17360  return var->probindex;
17361 }
17362 
17363 /** gets transformed variable of ORIGINAL variable */
17365  SCIP_VAR* var /**< problem variable */
17366  )
17367 {
17368  assert(var != NULL);
17369  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17370 
17371  return var->data.original.transvar;
17372 }
17373 
17374 /** gets column of COLUMN variable */
17376  SCIP_VAR* var /**< problem variable */
17377  )
17378 {
17379  assert(var != NULL);
17380  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17381 
17382  return var->data.col;
17383 }
17384 
17385 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17387  SCIP_VAR* var /**< problem variable */
17388  )
17389 {
17390  assert(var != NULL);
17391 
17392  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17393 }
17394 
17395 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17397  SCIP_VAR* var /**< problem variable */
17398  )
17399 {
17400  assert(var != NULL);
17402 
17403  return var->data.aggregate.var;
17404 }
17405 
17406 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17408  SCIP_VAR* var /**< problem variable */
17409  )
17410 {
17411  assert(var != NULL);
17413 
17414  return var->data.aggregate.scalar;
17415 }
17416 
17417 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17419  SCIP_VAR* var /**< problem variable */
17420  )
17421 {
17422  assert(var != NULL);
17424 
17425  return var->data.aggregate.constant;
17426 }
17427 
17428 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17430  SCIP_VAR* var /**< problem variable */
17431  )
17432 {
17433  assert(var != NULL);
17434  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17435  assert(!var->donotmultaggr);
17436 
17437  return var->data.multaggr.nvars;
17438 }
17439 
17440 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17442  SCIP_VAR* var /**< problem variable */
17443  )
17444 {
17445  assert(var != NULL);
17446  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17447  assert(!var->donotmultaggr);
17448 
17449  return var->data.multaggr.vars;
17450 }
17451 
17452 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17454  SCIP_VAR* var /**< problem variable */
17455  )
17456 {
17457  assert(var != NULL);
17458  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17459  assert(!var->donotmultaggr);
17460 
17461  return var->data.multaggr.scalars;
17462 }
17463 
17464 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17466  SCIP_VAR* var /**< problem variable */
17467  )
17468 {
17469  assert(var != NULL);
17470  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17471  assert(!var->donotmultaggr);
17472 
17473  return var->data.multaggr.constant;
17474 }
17475 
17476 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17478  SCIP_VAR* var /**< negated problem variable */
17479  )
17480 {
17481  assert(var != NULL);
17482 
17483  return var->negatedvar;
17484 }
17485 
17486 /** gets the negation variable x of a negated variable x' = offset - x */
17488  SCIP_VAR* var /**< negated problem variable */
17489  )
17490 {
17491  assert(var != NULL);
17492  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17493 
17494  return var->negatedvar;
17495 }
17496 
17497 /** gets the negation offset of a negated variable x' = offset - x */
17499  SCIP_VAR* var /**< negated problem variable */
17500  )
17501 {
17502  assert(var != NULL);
17503  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17504 
17505  return var->data.negate.constant;
17506 }
17507 
17508 /** gets objective function value of variable */
17510  SCIP_VAR* var /**< problem variable */
17511  )
17512 {
17513  assert(var != NULL);
17514 
17515  return var->obj;
17516 }
17517 
17518 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17520  SCIP_VAR* var /**< problem variable */
17521  )
17522 {
17523  assert(var != NULL);
17524 
17525  return var->unchangedobj;
17526 }
17527 
17528 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17529  * e.g. obj(x) = 1 this method returns for ~x the value -1
17530  */
17532  SCIP_VAR* var, /**< problem variable */
17533  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17534  )
17535 {
17536  SCIP_VAR* probvar = var;
17537  SCIP_Real mult = 1.0;
17538 
17539  assert(probvar != NULL);
17540  assert(aggrobj != NULL);
17541 
17542  while( probvar != NULL )
17543  {
17544  switch( SCIPvarGetStatus(probvar) )
17545  {
17547  case SCIP_VARSTATUS_LOOSE:
17548  case SCIP_VARSTATUS_COLUMN:
17549  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17550  return SCIP_OKAY;
17551 
17552  case SCIP_VARSTATUS_FIXED:
17553  assert(SCIPvarGetObj(probvar) == 0.0);
17554  (*aggrobj) = 0.0;
17555  return SCIP_OKAY;
17556 
17558  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17559  if ( probvar->data.multaggr.nvars == 1 )
17560  {
17561  assert( probvar->data.multaggr.vars != NULL );
17562  assert( probvar->data.multaggr.scalars != NULL );
17563  assert( probvar->data.multaggr.vars[0] != NULL );
17564  mult *= probvar->data.multaggr.scalars[0];
17565  probvar = probvar->data.multaggr.vars[0];
17566  break;
17567  }
17568  else
17569  {
17570  SCIP_Real tmpobj;
17571  int v;
17572 
17573  (*aggrobj) = 0.0;
17574 
17575  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17576  {
17577  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17578  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17579  }
17580  return SCIP_OKAY;
17581  }
17582 
17583  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17584  assert(probvar->data.aggregate.var != NULL);
17585  mult *= probvar->data.aggregate.scalar;
17586  probvar = probvar->data.aggregate.var;
17587  break;
17588 
17589  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17590  assert(probvar->negatedvar != NULL);
17591  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17592  assert(probvar->negatedvar->negatedvar == probvar);
17593  mult *= -1.0;
17594  probvar = probvar->negatedvar;
17595  break;
17596 
17597  default:
17598  SCIPABORT();
17599  return SCIP_INVALIDDATA; /*lint !e527*/
17600  }
17601  }
17602 
17603  return SCIP_INVALIDDATA;
17604 }
17605 
17606 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17608  SCIP_VAR* var /**< original problem variable */
17609  )
17610 {
17611  assert(var != NULL);
17612  assert(SCIPvarIsOriginal(var));
17613 
17615  return var->data.original.origdom.lb;
17616  else
17617  {
17618  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17619  assert(var->negatedvar != NULL);
17621 
17622  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17623  }
17624 }
17625 
17626 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17628  SCIP_VAR* var /**< original problem variable */
17629  )
17630 {
17631  assert(var != NULL);
17632  assert(SCIPvarIsOriginal(var));
17633 
17635  return var->data.original.origdom.ub;
17636  else
17637  {
17638  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17639  assert(var->negatedvar != NULL);
17641 
17642  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17643  }
17644 }
17645 
17646 /** gets the original hole list of an original variable */
17648  SCIP_VAR* var /**< problem variable */
17649  )
17650 {
17651  assert(var != NULL);
17652  assert(SCIPvarIsOriginal(var));
17653 
17655  return var->data.original.origdom.holelist;
17656 
17657  return NULL;
17658 }
17659 
17660 /** gets global lower bound of variable */
17662  SCIP_VAR* var /**< problem variable */
17663  )
17664 {
17665  assert(var != NULL);
17666 
17667  return var->glbdom.lb;
17668 }
17669 
17670 /** gets global upper bound of variable */
17672  SCIP_VAR* var /**< problem variable */
17673  )
17674 {
17675  assert(var != NULL);
17676 
17677  return var->glbdom.ub;
17678 }
17679 
17680 /** gets the global hole list of an active variable */
17682  SCIP_VAR* var /**< problem variable */
17683  )
17684 {
17685  assert(var != NULL);
17686 
17687  return var->glbdom.holelist;
17688 }
17689 
17690 /** gets best global bound of variable with respect to the objective function */
17692  SCIP_VAR* var /**< problem variable */
17693  )
17694 {
17695  assert(var != NULL);
17696 
17697  if( var->obj >= 0.0 )
17698  return var->glbdom.lb;
17699  else
17700  return var->glbdom.ub;
17701 }
17702 
17703 /** gets worst global bound of variable with respect to the objective function */
17705  SCIP_VAR* var /**< problem variable */
17706  )
17707 {
17708  assert(var != NULL);
17709 
17710  if( var->obj >= 0.0 )
17711  return var->glbdom.ub;
17712  else
17713  return var->glbdom.lb;
17714 }
17715 
17716 /** gets current lower bound of variable */
17718  SCIP_VAR* var /**< problem variable */
17719  )
17720 {
17721  assert(var != NULL);
17722 
17723  return var->locdom.lb;
17724 }
17725 
17726 /** gets current upper bound of variable */
17728  SCIP_VAR* var /**< problem variable */
17729  )
17730 {
17731  assert(var != NULL);
17732 
17733  return var->locdom.ub;
17734 }
17735 
17736 /** gets the current hole list of an active variable */
17738  SCIP_VAR* var /**< problem variable */
17739  )
17740 {
17741  assert(var != NULL);
17742 
17743  return var->locdom.holelist;
17744 }
17745 
17746 /** gets best local bound of variable with respect to the objective function */
17748  SCIP_VAR* var /**< problem variable */
17749  )
17750 {
17751  assert(var != NULL);
17752 
17753  if( var->obj >= 0.0 )
17754  return var->locdom.lb;
17755  else
17756  return var->locdom.ub;
17757 }
17758 
17759 /** gets worst local bound of variable with respect to the objective function */
17761  SCIP_VAR* var /**< problem variable */
17762  )
17763 {
17764  assert(var != NULL);
17765 
17766  if( var->obj >= 0.0 )
17767  return var->locdom.ub;
17768  else
17769  return var->locdom.lb;
17770 }
17771 
17772 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17774  SCIP_VAR* var /**< problem variable */
17775  )
17776 {
17777  assert(var != NULL);
17778 
17779  if( var->obj >= 0.0 )
17780  return SCIP_BOUNDTYPE_LOWER;
17781  else
17782  return SCIP_BOUNDTYPE_UPPER;
17783 }
17784 
17785 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17787  SCIP_VAR* var /**< problem variable */
17788  )
17789 {
17790  assert(var != NULL);
17791 
17792  if( var->obj >= 0.0 )
17793  return SCIP_BOUNDTYPE_UPPER;
17794  else
17795  return SCIP_BOUNDTYPE_LOWER;
17796 }
17797 
17798 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17800  SCIP_VAR* var /**< problem variable */
17801  )
17802 {
17803  assert(var != NULL);
17804 
17805  return var->lazylb;
17806 }
17807 
17808 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17810  SCIP_VAR* var /**< problem variable */
17811  )
17812 {
17813  assert(var != NULL);
17814 
17815  return var->lazyub;
17816 }
17817 
17818 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17819  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17820  */
17822  SCIP_VAR* var /**< problem variable */
17823  )
17824 {
17825  assert(var != NULL);
17826 
17827  return var->branchfactor;
17828 }
17829 
17830 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17831  * with lower priority
17832  */
17834  SCIP_VAR* var /**< problem variable */
17835  )
17836 {
17837  assert(var != NULL);
17838 
17839  return var->branchpriority;
17840 }
17841 
17842 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17844  SCIP_VAR* var /**< problem variable */
17845  )
17846 {
17847  assert(var != NULL);
17848 
17849  return (SCIP_BRANCHDIR)var->branchdirection;
17850 }
17851 
17852 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17853 int SCIPvarGetNVlbs(
17854  SCIP_VAR* var /**< problem variable */
17855  )
17856 {
17857  assert(var != NULL);
17858 
17859  return SCIPvboundsGetNVbds(var->vlbs);
17860 }
17861 
17862 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17863  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17864  */
17866  SCIP_VAR* var /**< problem variable */
17867  )
17868 {
17869  assert(var != NULL);
17870 
17871  return SCIPvboundsGetVars(var->vlbs);
17872 }
17873 
17874 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17876  SCIP_VAR* var /**< problem variable */
17877  )
17878 {
17879  assert(var != NULL);
17880 
17881  return SCIPvboundsGetCoefs(var->vlbs);
17882 }
17883 
17884 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17886  SCIP_VAR* var /**< problem variable */
17887  )
17888 {
17889  assert(var != NULL);
17890 
17891  return SCIPvboundsGetConstants(var->vlbs);
17892 }
17893 
17894 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17895 int SCIPvarGetNVubs(
17896  SCIP_VAR* var /**< problem variable */
17897  )
17898 {
17899  assert(var != NULL);
17900 
17901  return SCIPvboundsGetNVbds(var->vubs);
17902 }
17903 
17904 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17905  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17906  */
17908  SCIP_VAR* var /**< problem variable */
17909  )
17910 {
17911  assert(var != NULL);
17912 
17913  return SCIPvboundsGetVars(var->vubs);
17914 }
17915 
17916 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17918  SCIP_VAR* var /**< problem variable */
17919  )
17920 {
17921  assert(var != NULL);
17922 
17923  return SCIPvboundsGetCoefs(var->vubs);
17924 }
17925 
17926 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17928  SCIP_VAR* var /**< problem variable */
17929  )
17930 {
17931  assert(var != NULL);
17932 
17933  return SCIPvboundsGetConstants(var->vubs);
17934 }
17935 
17936 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17937  * there are no implications for nonbinary variable x
17938  */
17939 int SCIPvarGetNImpls(
17940  SCIP_VAR* var, /**< active problem variable */
17941  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17942  )
17943 {
17944  assert(var != NULL);
17945  assert(SCIPvarIsActive(var));
17946 
17947  return SCIPimplicsGetNImpls(var->implics, varfixing);
17948 }
17949 
17950 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17951  * problem variable x, there are no implications for nonbinary variable x;
17952  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17953  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17954  * (see SCIPvarGetIndex())
17955  */
17957  SCIP_VAR* var, /**< active problem variable */
17958  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17959  )
17960 {
17961  assert(var != NULL);
17962  assert(SCIPvarIsActive(var));
17963 
17964  return SCIPimplicsGetVars(var->implics, varfixing);
17965 }
17966 
17967 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17968  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17969  * there are no implications for nonbinary variable x
17970  */
17972  SCIP_VAR* var, /**< active problem variable */
17973  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17974  )
17975 {
17976  assert(var != NULL);
17977  assert(SCIPvarIsActive(var));
17978 
17979  return SCIPimplicsGetTypes(var->implics, varfixing);
17980 }
17981 
17982 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17983  * variable x, there are no implications for nonbinary variable x
17984  */
17986  SCIP_VAR* var, /**< active problem variable */
17987  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17988  )
17989 {
17990  assert(var != NULL);
17991  assert(SCIPvarIsActive(var));
17992 
17993  return SCIPimplicsGetBounds(var->implics, varfixing);
17994 }
17995 
17996 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17997  * there are no implications for nonbinary variable x.
17998  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17999  * its id is negative, otherwise it is nonnegative.
18000  */
18001 int* SCIPvarGetImplIds(
18002  SCIP_VAR* var, /**< active problem variable */
18003  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18004  )
18005 {
18006  assert(var != NULL);
18007  assert(SCIPvarIsActive(var));
18008 
18009  return SCIPimplicsGetIds(var->implics, varfixing);
18010 }
18011 
18012 /** gets number of cliques, the active variable is contained in */
18013 int SCIPvarGetNCliques(
18014  SCIP_VAR* var, /**< active problem variable */
18015  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18016  )
18017 {
18018  assert(var != NULL);
18019 
18020  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18021 }
18022 
18023 /** gets array of cliques, the active variable is contained in */
18025  SCIP_VAR* var, /**< active problem variable */
18026  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18027  )
18028 {
18029  assert(var != NULL);
18030 
18031  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18032 }
18033 
18034 /** gets primal LP solution value of variable */
18036  SCIP_VAR* var /**< problem variable */
18037  )
18038 {
18039  assert(var != NULL);
18040 
18042  return SCIPcolGetPrimsol(var->data.col);
18043  else
18044  return SCIPvarGetLPSol_rec(var);
18045 }
18046 
18047 /** gets primal NLP solution value of variable */
18049  SCIP_VAR* var /**< problem variable */
18050  )
18051 {
18052  assert(var != NULL);
18053 
18055  return var->nlpsol;
18056  else
18057  return SCIPvarGetNLPSol_rec(var);
18058 }
18059 
18060 /** return lower bound change info at requested position */
18062  SCIP_VAR* var, /**< problem variable */
18063  int pos /**< requested position */
18064  )
18065 {
18066  assert(pos >= 0);
18067  assert(pos < var->nlbchginfos);
18068 
18069  return &var->lbchginfos[pos];
18070 }
18071 
18072 /** gets the number of lower bound change info array */
18074  SCIP_VAR* var /**< problem variable */
18075  )
18076 {
18077  return var->nlbchginfos;
18078 }
18079 
18080 /** return upper bound change info at requested position */
18082  SCIP_VAR* var, /**< problem variable */
18083  int pos /**< requested position */
18084  )
18085 {
18086  assert(pos >= 0);
18087  assert(pos < var->nubchginfos);
18088 
18089  return &var->ubchginfos[pos];
18090 }
18091 
18092 /** gets the number upper bound change info array */
18094  SCIP_VAR* var /**< problem variable */
18095  )
18096 {
18097  assert(var != NULL);
18098 
18099  return var->nubchginfos;
18100 }
18101 
18102 /** returns the value based history for the variable */
18104  SCIP_VAR* var /**< problem variable */
18105  )
18106 {
18107  assert(var != NULL);
18108 
18109  return var->valuehistory;
18110 }
18111 
18112 /** gets pseudo solution value of variable */
18114  SCIP_VAR* var /**< problem variable */
18115  )
18116 {
18117  assert(var != NULL);
18118 
18120  return SCIPvarGetBestBoundLocal(var);
18121  else
18122  return SCIPvarGetPseudoSol_rec(var);
18123 }
18124 
18125 /** returns the variable's VSIDS score */
18127  SCIP_VAR* var, /**< problem variable */
18128  SCIP_STAT* stat, /**< problem statistics */
18129  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18130  )
18131 {
18132  assert(var != NULL);
18133 
18135  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18136  else
18137  return SCIPvarGetVSIDS_rec(var, stat, dir);
18138 }
18139 
18140 /** includes event handler with given data in variable's event filter */
18142  SCIP_VAR* var, /**< problem variable */
18143  BMS_BLKMEM* blkmem, /**< block memory */
18144  SCIP_SET* set, /**< global SCIP settings */
18145  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18146  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18147  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18148  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18149  )
18150 {
18151  assert(var != NULL);
18152  assert(set != NULL);
18153  assert(var->scip == set->scip);
18154  assert(var->eventfilter != NULL);
18155  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18156  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18157  assert(SCIPvarIsTransformed(var));
18158 
18159  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18160  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18161 
18162  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18163 
18164  return SCIP_OKAY;
18165 }
18166 
18167 /** deletes event handler with given data from variable's event filter */
18169  SCIP_VAR* var, /**< problem variable */
18170  BMS_BLKMEM* blkmem, /**< block memory */
18171  SCIP_SET* set, /**< global SCIP settings */
18172  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18173  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18174  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18175  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18176  )
18177 {
18178  assert(var != NULL);
18179  assert(set != NULL);
18180  assert(var->scip == set->scip);
18181  assert(var->eventfilter != NULL);
18182  assert(SCIPvarIsTransformed(var));
18183 
18184  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18185  (void*)eventdata);
18186 
18187  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18188 
18189  return SCIP_OKAY;
18190 }
18191 
18192 /** returns the position of the bound change index */
18193 int SCIPbdchgidxGetPos(
18194  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18195  )
18196 {
18197  assert(bdchgidx != NULL);
18198 
18199  return bdchgidx->pos;
18200 }
18201 
18202 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18204  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18205  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18206  )
18207 {
18208  assert(bdchgidx1 != NULL);
18209  assert(bdchgidx1->depth >= -2);
18210  assert(bdchgidx1->pos >= 0);
18211  assert(bdchgidx2 != NULL);
18212  assert(bdchgidx2->depth >= -2);
18213  assert(bdchgidx2->pos >= 0);
18214 
18215  return (bdchgidx1->depth < bdchgidx2->depth)
18216  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18217 }
18218 
18219 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18220  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18221  * last bound change was applied to the current node
18222  */
18224  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18225  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18226  )
18227 {
18228  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18229  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18230  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18231  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18232 
18233  if( bdchgidx1 == NULL )
18234  return FALSE;
18235  else if( bdchgidx2 == NULL )
18236  return TRUE;
18237  else
18238  return (bdchgidx1->depth < bdchgidx2->depth)
18239  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18240 }
18241 
18242 /** returns old bound that was overwritten for given bound change information */
18244  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18245  )
18246 {
18247  assert(bdchginfo != NULL);
18248 
18249  return bdchginfo->oldbound;
18250 }
18251 
18252 /** returns new bound installed for given bound change information */
18254  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18255  )
18256 {
18257  assert(bdchginfo != NULL);
18258 
18259  return bdchginfo->newbound;
18260 }
18261 
18262 /** returns variable that belongs to the given bound change information */
18264  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18265  )
18266 {
18267  assert(bdchginfo != NULL);
18268 
18269  return bdchginfo->var;
18270 }
18271 
18272 /** returns whether the bound change information belongs to a branching decision or a deduction */
18274  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18275  )
18276 {
18277  assert(bdchginfo != NULL);
18278 
18279  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18280 }
18281 
18282 /** returns whether the bound change information belongs to a lower or upper bound change */
18284  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18285  )
18286 {
18287  assert(bdchginfo != NULL);
18288 
18289  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18290 }
18291 
18292 /** returns depth level of given bound change information */
18294  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18295  )
18296 {
18297  assert(bdchginfo != NULL);
18298 
18299  return bdchginfo->bdchgidx.depth;
18300 }
18301 
18302 /** returns bound change position in its depth level of given bound change information */
18304  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18305  )
18306 {
18307  assert(bdchginfo != NULL);
18308 
18309  return bdchginfo->bdchgidx.pos;
18310 }
18311 
18312 /** returns bound change index of given bound change information */
18314  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18315  )
18316 {
18317  assert(bdchginfo != NULL);
18318 
18319  return &bdchginfo->bdchgidx;
18320 }
18321 
18322 /** returns inference variable of given bound change information */
18324  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18325  )
18326 {
18327  assert(bdchginfo != NULL);
18330 
18331  return bdchginfo->inferencedata.var;
18332 }
18333 
18334 /** returns inference constraint of given bound change information */
18336  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18337  )
18338 {
18339  assert(bdchginfo != NULL);
18341  assert(bdchginfo->inferencedata.reason.cons != NULL);
18342 
18343  return bdchginfo->inferencedata.reason.cons;
18344 }
18345 
18346 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18348  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18349  )
18350 {
18351  assert(bdchginfo != NULL);
18353 
18354  return bdchginfo->inferencedata.reason.prop;
18355 }
18356 
18357 /** returns inference user information of given bound change information */
18359  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18360  )
18361 {
18362  assert(bdchginfo != NULL);
18365 
18366  return bdchginfo->inferencedata.info;
18367 }
18368 
18369 /** returns inference bound of inference variable of given bound change information */
18371  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18372  )
18373 {
18374  assert(bdchginfo != NULL);
18377 
18378  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18379 }
18380 
18381 /** returns the relaxed bound change type */
18383  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18384  )
18385 {
18386  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18387 }
18388 
18389 
18390 /** returns whether the bound change information belongs to a redundant bound change */
18392  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18393  )
18394 {
18395  assert(bdchginfo != NULL);
18396  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18397 
18398  return bdchginfo->redundant;
18399 }
18400 
18401 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18403  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18404  )
18405 {
18406  assert(bdchginfo != NULL);
18407 
18410  && bdchginfo->inferencedata.reason.prop != NULL);
18411 }
18412 
18413 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18414  * has a tighter new bound as the second bound change
18415  */
18417  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18418  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18419  )
18420 {
18421  assert(bdchginfo1 != NULL);
18422  assert(bdchginfo2 != NULL);
18423  assert(bdchginfo1->var == bdchginfo2->var);
18424  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18425 
18426  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18427  ? bdchginfo1->newbound > bdchginfo2->newbound
18428  : bdchginfo1->newbound < bdchginfo2->newbound);
18429 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:562
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11757
SCIP_HOLELIST * holelist
Definition: struct_var.h:163
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1812
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:95
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18383
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17748
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1657
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1515
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:3095
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15164
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5980
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17154
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3325
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:459
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13884
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:929
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9186
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:15291
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:87
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:575
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3351
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:17167
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6038
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6488
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:494
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17738
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:14811
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9068
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13578
SCIP_RETCODE SCIPvarAddVub(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vubvar, SCIP_Real vubcoef, SCIP_Real vubconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10269
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17022
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13044
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:478
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13768
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17669
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17408
int nubchginfos
Definition: struct_var.h:263
internal methods for branch and bound tree
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:112
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:607
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16072
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:231
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5887
unsigned int inferboundtype
Definition: struct_var.h:93
unsigned int relaxationonly
Definition: struct_var.h:279
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17387
char * name
Definition: struct_var.h:229
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:966
int SCIPvarGetNLocksUpType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3250
unsigned int boundchgtype
Definition: struct_var.h:114
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16563
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:1125
SCIP_HOLE hole
Definition: struct_var.h:51
SCIP_Real bestrootsol
Definition: struct_var.h:207
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6167
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17365
static SCIP_RETCODE varProcessChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6639
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6378
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1687
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:138
SCIP_RETCODE SCIPvarChgLbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6989
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:87
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5724
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:2046
public methods for implications, variable bounds, and cliques
SCIP_EXPORT SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14378
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18049
methods for implications, variable bounds, and cliques
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17077
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:2231
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1446
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14544
#define SCIP_MAXSTRLEN
Definition: def.h:273
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:18104
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15459
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:805
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3302
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6371
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17822
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17810
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:591
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6103
SCIP_Real lastbranchvalue
Definition: struct_stat.h:131
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1036
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:250
static void printHolelist(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2872
#define MAXABSVBCOEF
Definition: var.c:71
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1696
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:13178
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18392
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16126
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:1970
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7273
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18036
SCIP_Real constant
Definition: struct_var.h:184
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1182
SCIP_Real bestrootredcost
Definition: struct_var.h:208
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8370
SCIP_HISTORY * historycrun
Definition: struct_var.h:245
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:175
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18082
SCIP_EXPORT SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7420
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9008
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17245
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3417
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1431
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6430
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:112
SCIP_Longint closestvblpcount
Definition: struct_var.h:247
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8678
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:2423
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:6566
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3269
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5845
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:154
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3687
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2318
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:243
static SCIP_RETCODE boundchgApplyGlobal(SCIP_BOUNDCHG *boundchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:837
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5947
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14897
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12698
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18114
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:129
unsigned int nboundchgs
Definition: struct_var.h:123
SCIP_RETCODE SCIPvarCatchEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: var.c:18142
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17192
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:3268
SCIP_HOLELIST * newlist
Definition: struct_var.h:59
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17957
SCIP_Real right
Definition: struct_var.h:45
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:317
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5867
#define NLOCKTYPES
Definition: type_var.h:81
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:42
#define FALSE
Definition: def.h:73
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10721
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:188
#define EPSISINT(x, eps)
Definition: def.h:200
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:17659
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6521
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:481
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:107
SCIP_RETCODE SCIPdomchgUndo(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:1275
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17510
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16909
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:752
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3357
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16959
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:69
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:258
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17682
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3046
SCIP_Real constant
Definition: struct_var.h:194
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:12235
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6092
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:279
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:17177
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14783
#define TRUE
Definition: def.h:72
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5848
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15120
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:111
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:54
SCIP_HOLELIST * oldlist
Definition: struct_var.h:60
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15592
#define MAXIMPLSCLOSURE
Definition: var.c:68
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:691
int nlbchginfos
Definition: struct_var.h:261
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16583
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1685
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:2003
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12627
SCIP_RETCODE SCIPvarAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10716
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:181
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8053
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5882
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5573
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:66
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17053
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:8027
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2831
SCIP_RETCODE SCIPvarChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:7132
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17335
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12835
static SCIP_RETCODE varCreate(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, const char *name, SCIP_Real lb, SCIP_Real ub, SCIP_Real obj, SCIP_VARTYPE vartype, SCIP_Bool initial, SCIP_Bool removable, SCIP_DECL_VARCOPY((*varcopy)), SCIP_DECL_VARDELORIG((*vardelorig)), SCIP_DECL_VARTRANS((*vartrans)), SCIP_DECL_VARDELTRANS((*vardeltrans)), SCIP_VARDATA *vardata)
Definition: var.c:1859
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:827
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15827
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17256
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17986
SCIP_EXPORT void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:520
#define SCIPdebugMessage
Definition: pub_message.h:87
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:11039
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11700
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1542
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11772
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16812
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17131
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18194
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11765
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3426
int index
Definition: struct_var.h:248
SCIP_Real constant
Definition: struct_var.h:177
unsigned int domchgtype
Definition: struct_var.h:142
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6114
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_VARTYPE vartype)
Definition: var.c:5982
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1456
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13478
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16638
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14139
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1692
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6321
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1177
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:249
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11585
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:675
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3336
SCIP_HOLECHG * holechgs
Definition: struct_var.h:134
SCIP_Real obj
Definition: struct_var.h:203
SCIP_EXPORT SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7700
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:5516
SCIP_Real relaxsol
Definition: struct_var.h:210
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1536
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:897
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6178
int conflictlbcount
Definition: struct_var.h:264
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13757
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:5857
internal methods for LP management
Definition: heur_padm.c:125
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16822
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17866
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12907
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:430
SCIP_VAR ** vars
Definition: struct_var.h:186
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:195
real eps
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:212
int branchpriority
Definition: struct_var.h:259
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:596
internal methods for collecting primal CIP solutions and primal informations
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip_tree.c:62
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1338
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:2276
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17454
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:197
SCIP_VAR * var
Definition: struct_var.h:178
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:112
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12768
int nrootboundchgs
Definition: struct_stat.h:210
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17065
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:151
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6074
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:7350
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:170
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13114
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15688
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:508
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18324
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1415
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17213
SCIP_Real conflictrelaxedub
Definition: struct_var.h:216
unsigned int inferboundtype
Definition: struct_var.h:116
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17299
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:553
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:7774
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18274
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3362
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6020
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12652
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:272
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4420
public methods for managing constraints
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11265
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:444
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:13231
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:17099
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16949
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:794
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16967
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:250
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:215
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11455
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14237
SCIP_AGGREGATE aggregate
Definition: struct_var.h:225
SCIP_Real lazylb
Definition: struct_var.h:217
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13021
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:453
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17012
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:7388
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17325
SCIP_RETCODE SCIPdomchgApplyGlobal(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool *cutoff)
Definition: var.c:1310
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:1877
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4435
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7296
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:7608
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4404
enum SCIP_LockType SCIP_LOCKTYPE
Definition: type_var.h:87
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:17203
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18417
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:533
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3311
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:13227
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18002
#define SCIPerrorMessage
Definition: pub_message.h:55
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:14274
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:12044
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10691
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1259
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1088
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:237
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:987
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:16580
SCIP_Bool SCIPvarPscostThresholdProbabilityTest(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var, SCIP_Real frac, SCIP_Real threshold, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14687
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:380
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:907
SCIP_Longint lpcount
Definition: struct_stat.h:178
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17478
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15982
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17800
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17940
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:624
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:6069
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16929
int lbchginfossize
Definition: struct_var.h:260
unsigned int varstatus
Definition: struct_var.h:274
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17787
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17834
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18294
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2786
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:688
SCIP_Real bestrootlpobjval
Definition: struct_var.h:209
SCIP_VARDATA * vardata
Definition: struct_var.h:234
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6258
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17532
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:189
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14286
SCIP_Real primsolavg
Definition: struct_var.h:212
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LOCKTYPE locktype, int addnlocksdown, int addnlocksup)
Definition: var.c:3067
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17918
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:932
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3443
#define SCIPdebugCheckAggregation(set, var, aggrvars, scalars, constant, naggrvars)
Definition: debug.h:251
SCIP_HOLECHG * holechgs
Definition: struct_var.h:144
static SCIP_RETCODE varProcessChgUbGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound)
Definition: var.c:6815
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:113
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1827
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:164
static SCIP_RETCODE tryAggregateIntVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4929
SCIP_VAR * transvar
Definition: struct_var.h:170
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:155
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6556
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:101
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:418
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1689
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:549
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:665
unsigned int initial
Definition: struct_var.h:268
#define NULL
Definition: lpi_spx1.cpp:155
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13959
SCIP_NEGATE negate
Definition: struct_var.h:227
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16303
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:79
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:7441
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13624
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:169
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17088
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3277
#define REALABS(x)
Definition: def.h:187
int nparentvars
Definition: struct_var.h:255
SCIP_Real unchangedobj
Definition: struct_var.h:204
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11670
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16226
SCIP_RETCODE SCIPvarAddVlb(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *vlbvar, SCIP_Real vlbcoef, SCIP_Real vlbconstant, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9805
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15028
internal methods for global SCIP settings
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14506
#define SCIP_CALL(x)
Definition: def.h:364
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17896
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16855
SCIP_VBOUNDS * vubs
Definition: struct_var.h:238
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6466
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:185
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:15207
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16832
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2354
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15739
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14333
static SCIP_RETCODE varAddTransitiveBinaryClosureImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9524
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5675
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3285
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18348
Definition: grphload.c:88
int closestvubidx
Definition: struct_var.h:267
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14421
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:468
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6002
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11399
SCIP_Real vsidsweight
Definition: struct_stat.h:120
SCIP_RETCODE SCIPvarChgUbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7901
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:245
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17419
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15075
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16170
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2906
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17499
SCIP_EXPORT void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
unsigned int branchdirection
Definition: struct_var.h:276
int ubchginfossize
Definition: struct_var.h:262
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1579
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6422
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10935
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:246
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:113
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:324
int var_probindex
Definition: struct_lp.h:169
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16586
int nlocksdown[NLOCKTYPES]
Definition: struct_var.h:257
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6355
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3347
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17376
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:456
internal methods for problem variables
static SCIP_RETCODE varEventObjChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_PRIMAL *primal, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldobj, SCIP_Real newobj)
Definition: var.c:6034
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11329
SCIP_RETCODE SCIPvarTryAggregateVars(SCIP_SET *set, BMS_BLKMEM *blkmem, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *varx, SCIP_VAR *vary, SCIP_Real scalarx, SCIP_Real scalary, SCIP_Real rhs, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5155
#define SCIP_UNKNOWN
Definition: def.h:184
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6125
public data structures and miscellaneous methods
unsigned int vartype
Definition: struct_var.h:273
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10915
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:460
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17488
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:15375
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:6490
SCIP_VAR * var
Definition: struct_var.h:90
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:88
static SCIP_RETCODE varProcessAddHoleLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8797
int SCIPgetDepth(SCIP *scip)
Definition: scip_tree.c:638
#define SCIP_Bool
Definition: def.h:70
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17466
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2774
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18403
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18204
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:447
const char * SCIPgetProbName(SCIP *scip)
Definition: scip_prob.c:1065
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4626
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11984
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16979
unsigned int deletable
Definition: struct_var.h:270
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15784
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5900
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17115
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6207
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17672
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13033
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3644
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17774
SCIP_Bool divingobjchg
Definition: struct_lp.h:371
SCIP_MULTAGGR multaggr
Definition: struct_var.h:226
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8143
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:458
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:619
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:9281
unsigned int deleted
Definition: struct_var.h:271
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3332
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3746
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17761
#define MAX(x, y)
Definition: tclique_def.h:83
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3293
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11751
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18359
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17141
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:555
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15547
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17520
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3363
public methods for LP management
unsigned int removable
Definition: struct_var.h:269
#define SCIPsetDebugMsg
Definition: set.h:1721
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3312
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:17042
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2570
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8436
unsigned int redundant
Definition: struct_var.h:95
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15504
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11162
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16623
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18224
int closestvlbidx
Definition: struct_var.h:266
#define EPSLE(x, y, eps)
Definition: def.h:190
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:4309
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18284
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18371
int nuses
Definition: struct_var.h:256
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15884
SCIP_RETCODE SCIPvarFixBinary(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10948
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11201
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:72
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:126
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:162
int probindex
Definition: struct_var.h:249
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8549
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17233
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17608
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:2088
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13685
datastructures for problem statistics
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18025
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:623
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6400
SCIP_RETCODE SCIPcliquetableAdd(SCIP_CLIQUETABLE *cliquetable, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR **vars, SCIP_Bool *values, int nvars, SCIP_Bool isequation, SCIP_Bool *infeasible, int *nbdchgs)
Definition: implics.c:2350
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1495
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:6144
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:14947
static SCIP_RETCODE varAddImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool isshortcut, SCIP_Bool *infeasible, int *nbdchgs, SCIP_Bool *added)
Definition: var.c:9316
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17718
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3791
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16999
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3366
SCIP * scip
Definition: struct_var.h:201
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:241
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12955
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2253
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18304
int conflictubcount
Definition: struct_var.h:265
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3261
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2200
SCIP_DOM locdom
Definition: struct_var.h:220
static SCIP_RETCODE varAddTransitiveImplic(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool transitive, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9597
int SCIPvarGetNLocksDownType(SCIP_VAR *var, SCIP_LOCKTYPE locktype)
Definition: var.c:3193
#define SCIP_REAL_MAX
Definition: def.h:164
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6710
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:246
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2844
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:406
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:118
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:662
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17705
datastructures for storing and manipulating the main problem
SCIP_RETCODE SCIPvarAddToRow(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp, SCIP_ROW *row, SCIP_Real val)
Definition: var.c:14031
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3508
SCIP_Real newbound
Definition: struct_var.h:84
#define SCIP_REAL_MIN
Definition: def.h:165
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3549
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17728
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:235
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:421
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2598
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6545
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:153
SCIP_VAR ** b
Definition: circlepacking.c:56
SCIP_RETCODE SCIPvarChgBdGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7322
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18264
#define SCIP_DEFAULT_INFINITY
Definition: def.h:168
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1202
SCIP_HOLELIST * next
Definition: struct_var.h:52
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6195
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18336
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:636
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:444
unsigned int boundtype
Definition: struct_var.h:115
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1699
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:834
static const SCIP_Real scalars[]
Definition: lp.c:5731
SCIP_RETCODE SCIPvarMultiaggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTFILTER *eventfilter, SCIP_EVENTQUEUE *eventqueue, int naggvars, SCIP_VAR **aggvars, SCIP_Real *scalars, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:5321
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8430
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3474
SCIP_RETCODE SCIPnodeAddBoundchg(SCIP_NODE *node, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_Bool probingchange)
Definition: tree.c:2075
SCIP_Real lazyub
Definition: struct_var.h:218
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1837
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:143
unsigned int redundant
Definition: struct_var.h:117
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15939
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17662
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:3814
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16964
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12328
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17876
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17430
SCIP_Bool SCIPvarSignificantPscostDifference(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *varx, SCIP_Real fracx, SCIP_VAR *vary, SCIP_Real fracy, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool onesided)
Definition: var.c:14621
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17886
data structures for LP management
int nrootboundchgsrun
Definition: struct_stat.h:211
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3435
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:18062
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10590
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:609
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:9088
SCIP_Real * scalars
Definition: struct_var.h:185
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18094
SCIP_IMPLICS * implics
Definition: struct_var.h:239
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6056
datastructures for problem variables
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17269
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:103
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:354
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:9035
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8089
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:151
static SCIP_RETCODE applyImplic(BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:9217
union SCIP_Var::@14 data
#define SCIP_Real
Definition: def.h:163
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:121
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2671
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:1226
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16422
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6499
SCIP_RETCODE SCIPeventCreateTypeChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_VARTYPE oldtype, SCIP_VARTYPE newtype)
Definition: event.c:824
int parentvarssize
Definition: struct_var.h:254
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:240
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2363
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12540
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14253
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:18127
#define SCIP_INVALID
Definition: def.h:183
internal methods for constraints and constraint handlers
SCIP_RETCODE SCIPeventCreateGholeAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real left, SCIP_Real right)
Definition: event.c:717
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:2487
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16282
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2232
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:575
void SCIPvarMarkRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17314
SCIP_Real branchfactor
Definition: struct_var.h:205
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17972
unsigned int donotmultaggr
Definition: struct_var.h:272
#define SCIP_Longint
Definition: def.h:148
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6699
SCIP_Real nlpsol
Definition: struct_var.h:211
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11244
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:171
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2546
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:16025
SCIP_Real lb
Definition: struct_var.h:161
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6444
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:8926
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8304
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2813
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16890
SCIP_DOM glbdom
Definition: struct_var.h:219
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5867
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:649
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16919
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2917
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17355
enum SCIP_Vartype SCIP_VARTYPE
Definition: type_var.h:60
static SCIP_RETCODE varEventGubChanged(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:6528
SCIP_Bool collectvarhistory
Definition: struct_stat.h:268
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12076
SCIP_VAR * negatedvar
Definition: struct_var.h:236
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17279
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3397
SCIP_Real newbound
Definition: struct_var.h:109
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3341
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8497
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16156
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6338
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6598
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:443
unsigned int delglobalstructs
Definition: struct_var.h:278
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6721
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17032
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:18169
SCIP_Real rootsol
Definition: struct_var.h:206
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2559
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:14129
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13609
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17397
SCIP_HISTORY * history
Definition: struct_var.h:244
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17628
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15637
int nrootintfixingsrun
Definition: struct_stat.h:213
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:429
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18014
union SCIP_BoundChg::@13 data
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12413
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:67
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16939
#define SCIP_CALL_ABORT(x)
Definition: def.h:343
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17648
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17223
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3320
SCIP_ORIGINAL original
Definition: struct_var.h:223
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3941
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9260
#define SCIP_ALLOC(x)
Definition: def.h:375
#define SCIPABORT()
Definition: def.h:336
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13544
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:642
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:57
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17844
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8238
unsigned int applied
Definition: struct_var.h:94
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16989
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17928
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:64
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:11124
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17908
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11964
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16543
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:449
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5936
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13824
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18244
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16711
SCIP_COL * col
Definition: struct_var.h:224
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5759
SCIP_Real left
Definition: struct_var.h:44
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition: var.c:1349
#define EPSZ(x, eps)
Definition: def.h:193
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17442
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18314
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18254
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:442
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11518
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:928
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17692
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6510
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17854
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14452
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17345
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:242
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14756
public methods for propagators
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1501
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:5628
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11708
SCIP_Real scalar
Definition: struct_var.h:176
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:142
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:18074
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11184