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-2021 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 ) /*lint !e774*/
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 ) /*lint !e774*/
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 !e587 !e650*/
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 !e587 !e650*/
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 !e587 !e650*/
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  /* check that the scalar and constant in the aggregation are not too large to avoid numerical problems */
5029  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5030  || REALABS((SCIP_Real)(b)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) /*lint !e653*/
5031  || REALABS((SCIP_Real)(a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5032  {
5033  return SCIP_OKAY;
5034  }
5035 
5036  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
5037  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
5038  {
5039  /* aggregate x = - b/a*y + c/a */
5040  /*lint --e{653}*/
5041  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5042  branchcand, eventfilter, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
5043  assert(*aggregated);
5044  return SCIP_OKAY;
5045  }
5046  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
5047  {
5048  /* aggregate y = - a/b*x + c/b */
5049  /*lint --e{653}*/
5050  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5051  branchcand, eventfilter, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
5052  assert(*aggregated);
5053  return SCIP_OKAY;
5054  }
5055 
5056  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
5057  * common divisor. Let (x',y') be a solution of the equality
5058  * a*x + b*y == c -> a*x == c - b*y
5059  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
5060  */
5061 
5062  /* find initial solution (x',y'):
5063  * - find y' such that c - b*y' is a multiple of a
5064  * - start in equivalence class c%a
5065  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
5066  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
5067  * - 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
5068  * - calculate x' with x' = (c - b*y')/a (which must be integral)
5069  *
5070  * Algorithm works for a > 0 only.
5071  */
5072  if( a < 0 )
5073  {
5074  a = -a;
5075  b = -b;
5076  c = -c;
5077  }
5078  assert(a > 0);
5079 
5080  /* search upwards from ysol = 0 */
5081  ysol = 0;
5082  currentclass = c % a;
5083  if( currentclass < 0 )
5084  currentclass += a;
5085  assert(0 <= currentclass && currentclass < a);
5086 
5087  classstep = (-b) % a;
5088 
5089  if( classstep < 0 )
5090  classstep += a;
5091  assert(0 <= classstep && classstep < a);
5092 
5093  while( currentclass != 0 )
5094  {
5095  assert(0 <= currentclass && currentclass < a);
5096  currentclass += classstep;
5097  if( currentclass >= a )
5098  currentclass -= a;
5099  ysol++;
5100  }
5101  assert(ysol < a);
5102  assert(((c - b*ysol) % a) == 0);
5103 
5104  xsol = (c - b*ysol)/a;
5105 
5106  /* determine variable type for new artificial variable:
5107  *
5108  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
5109  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
5110  * integral type
5111  */
5114 
5115  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
5116  * - create new integer variable z with infinite bounds
5117  * - aggregate variable x = -b*z + x'
5118  * - aggregate variable y = a*z + y'
5119  * - the bounds of z are calculated automatically during aggregation
5120  */
5121  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
5122  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
5123  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
5125  NULL, NULL, NULL, NULL, NULL) );
5126 
5127  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5128 
5129  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5130  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5131  assert(*aggregated || *infeasible);
5132 
5133  if( !(*infeasible) )
5134  {
5135  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5136  branchcand, eventfilter, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5137  assert(*aggregated || *infeasible);
5138  }
5139 
5140  /* release z */
5141  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5142 
5143  return SCIP_OKAY; /*lint !e438*/
5144 }
5145 
5146 /** performs second step of SCIPaggregateVars():
5147  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5148  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5149  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5150  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5151  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5152  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5153  *
5154  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5155  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5156  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5157  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5158  */
5160  SCIP_SET* set, /**< global SCIP settings */
5161  BMS_BLKMEM* blkmem, /**< block memory */
5162  SCIP_STAT* stat, /**< problem statistics */
5163  SCIP_PROB* transprob, /**< tranformed problem data */
5164  SCIP_PROB* origprob, /**< original problem data */
5165  SCIP_PRIMAL* primal, /**< primal data */
5166  SCIP_TREE* tree, /**< branch and bound tree */
5167  SCIP_REOPT* reopt, /**< reoptimization data structure */
5168  SCIP_LP* lp, /**< current LP data */
5169  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5170  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5171  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5172  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5173  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5174  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5175  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5176  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5177  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5178  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5179  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5180  )
5181 {
5182  SCIP_Bool easyaggr;
5183  SCIP_Real maxscalar;
5184  SCIP_Real absquot;
5185 
5186  assert(set != NULL);
5187  assert(blkmem != NULL);
5188  assert(stat != NULL);
5189  assert(transprob != NULL);
5190  assert(origprob != NULL);
5191  assert(tree != NULL);
5192  assert(lp != NULL);
5193  assert(cliquetable != NULL);
5194  assert(branchcand != NULL);
5195  assert(eventqueue != NULL);
5196  assert(varx != NULL);
5197  assert(vary != NULL);
5198  assert(varx != vary);
5199  assert(infeasible != NULL);
5200  assert(aggregated != NULL);
5201  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5202  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5203  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5204  assert(!SCIPsetIsZero(set, scalarx));
5205  assert(!SCIPsetIsZero(set, scalary));
5206 
5207  *infeasible = FALSE;
5208  *aggregated = FALSE;
5209 
5210  absquot = REALABS(scalarx / scalary);
5211  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5212  maxscalar = MAX(maxscalar, 1.0);
5213 
5214  if( absquot > maxscalar || absquot < 1 / maxscalar )
5215  return SCIP_OKAY;
5216 
5217  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5218  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5219  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5220  {
5221  SCIP_VAR* var;
5222  SCIP_Real scalar;
5223 
5224  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5225  var = vary;
5226  vary = varx;
5227  varx = var;
5228  scalar = scalary;
5229  scalary = scalarx;
5230  scalarx = scalar;
5231  }
5232 
5233  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5234  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5235  return SCIP_OKAY;
5236 
5237  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5238 
5239  /* figure out, which variable should be aggregated */
5240  easyaggr = FALSE;
5241 
5242  /* check if it is an easy aggregation that means:
5243  *
5244  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5245  */
5246  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5247  {
5249  {
5250  easyaggr = TRUE;
5251  }
5252  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5253  {
5254  easyaggr = TRUE;
5255  }
5256  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5257  {
5258  /* we have an easy aggregation if we flip the variables x and y */
5259  SCIP_VAR* var;
5260  SCIP_Real scalar;
5261 
5262  /* switch the variables, such that varx is the aggregated variable */
5263  var = vary;
5264  vary = varx;
5265  varx = var;
5266  scalar = scalary;
5267  scalary = scalarx;
5268  scalarx = scalar;
5269  easyaggr = TRUE;
5270  }
5271  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5272  {
5273  /* the aggregation is still easy if both variables are continuous */
5274  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5275  easyaggr = TRUE;
5276  }
5277  }
5278 
5279  /* did we find an "easy" aggregation? */
5280  if( easyaggr )
5281  {
5282  SCIP_Real scalar;
5283  SCIP_Real constant;
5284 
5285  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5286 
5287  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5288  scalar = -scalary/scalarx;
5289  constant = rhs/scalarx;
5290 
5291  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5292  return SCIP_OKAY;
5293 
5294  /* check aggregation for integer feasibility */
5297  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5298  {
5299  *infeasible = TRUE;
5300  return SCIP_OKAY;
5301  }
5302 
5303  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5304  * since then we would loose the corresponding divisibility property
5305  */
5306  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5307 
5308  /* aggregate the variable */
5309  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5310  branchcand, eventfilter, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5311  assert(*aggregated || *infeasible);
5312  }
5315  {
5316  /* the variables are both integral: we have to try to find an integer aggregation */
5317  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5318  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5319  }
5320 
5321  return SCIP_OKAY;
5322 }
5323 
5324 /** converts variable into multi-aggregated variable */
5326  SCIP_VAR* var, /**< problem variable */
5327  BMS_BLKMEM* blkmem, /**< block memory */
5328  SCIP_SET* set, /**< global SCIP settings */
5329  SCIP_STAT* stat, /**< problem statistics */
5330  SCIP_PROB* transprob, /**< tranformed problem data */
5331  SCIP_PROB* origprob, /**< original problem data */
5332  SCIP_PRIMAL* primal, /**< primal data */
5333  SCIP_TREE* tree, /**< branch and bound tree */
5334  SCIP_REOPT* reopt, /**< reoptimization data structure */
5335  SCIP_LP* lp, /**< current LP data */
5336  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5337  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5338  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5339  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5340  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5341  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5342  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5343  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5344  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5345  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5346  )
5347 {
5348  SCIP_VAR** tmpvars;
5349  SCIP_Real* tmpscalars;
5350  SCIP_Real obj;
5351  SCIP_Real branchfactor;
5352  int branchpriority;
5353  SCIP_BRANCHDIR branchdirection;
5354  int nlocksdown[NLOCKTYPES];
5355  int nlocksup[NLOCKTYPES];
5356  int v;
5357  SCIP_Real tmpconstant;
5358  SCIP_Real tmpscalar;
5359  int ntmpvars;
5360  int tmpvarssize;
5361  int tmprequiredsize;
5362  int i;
5363 
5364  assert(var != NULL);
5365  assert(var->scip == set->scip);
5366  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5367  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5368  assert(naggvars == 0 || aggvars != NULL);
5369  assert(naggvars == 0 || scalars != NULL);
5370  assert(infeasible != NULL);
5371  assert(aggregated != NULL);
5372 
5373  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5374 
5375  /* check multi-aggregation on debugging solution */
5376  SCIP_CALL( SCIPdebugCheckAggregation(set, var, aggvars, scalars, constant, naggvars) ); /*lint !e506 !e774*/
5377 
5378  *infeasible = FALSE;
5379  *aggregated = FALSE;
5380 
5381  switch( SCIPvarGetStatus(var) )
5382  {
5384  if( var->data.original.transvar == NULL )
5385  {
5386  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5387  return SCIP_INVALIDDATA;
5388  }
5389  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5390  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5391  break;
5392 
5393  case SCIP_VARSTATUS_LOOSE:
5394  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5395 
5396  /* check if we would create a self-reference */
5397  ntmpvars = naggvars;
5398  tmpvarssize = naggvars;
5399  tmpconstant = constant;
5400  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5401  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5402 
5403  /* get all active variables for multi-aggregation */
5404  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5405  if( tmprequiredsize > tmpvarssize )
5406  {
5407  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5408  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5409  tmpvarssize = tmprequiredsize;
5410  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5411  assert( tmprequiredsize <= tmpvarssize );
5412  }
5413 
5414  tmpscalar = 0.0;
5415 
5416  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5417  * possible multi-aggregated variable
5418  */
5419  for( v = ntmpvars - 1; v >= 0; --v )
5420  {
5421  assert(tmpvars[v] != NULL);
5422  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5423 
5424  if( tmpvars[v]->index == var->index )
5425  {
5426  tmpscalar += tmpscalars[v];
5427  tmpvars[v] = tmpvars[ntmpvars - 1];
5428  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5429  --ntmpvars;
5430  }
5431  }
5432 
5433  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5434  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5435  {
5436  if( ntmpvars == 0 )
5437  {
5438  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5439  {
5440  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5441  goto TERMINATE;
5442  }
5443  else /* 0 = c and c != 0 */
5444  {
5445  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5446  *infeasible = TRUE;
5447  goto TERMINATE;
5448  }
5449  }
5450  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5451  {
5452  assert(tmpscalars[0] != 0.0);
5453  assert(tmpvars[0] != NULL);
5454 
5455  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5456  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5457  branchcand, eventfilter, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5458  goto TERMINATE;
5459  }
5460  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 */
5461  {
5462  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5463 
5464  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5465  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5466 
5467  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5468  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5469  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5470 
5471  goto TERMINATE;
5472  }
5473  else
5474  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5475  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5476  */
5477  goto TERMINATE;
5478  }
5479  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5480  else if( !SCIPsetIsZero(set, tmpscalar) )
5481  {
5482  tmpscalar = 1 - tmpscalar;
5483  tmpconstant /= tmpscalar;
5484  for( v = ntmpvars - 1; v >= 0; --v )
5485  tmpscalars[v] /= tmpscalar;
5486  }
5487 
5488  /* check, if we are in one of the simple cases */
5489  if( ntmpvars == 0 )
5490  {
5491  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5492  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5493  eventfilter, eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5494  goto TERMINATE;
5495  }
5496 
5497  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5498  if( ntmpvars == 1 )
5499  {
5500  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5501  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5502 
5503  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5504  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5505  infeasible, aggregated) );
5506 
5507  goto TERMINATE;
5508  }
5509 
5510  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5511  * empty hole list; this should be changed in the future */
5512  if( SCIPvarGetHolelistGlobal(var) != NULL )
5513  goto TERMINATE;
5514 
5515  /* if the variable is not allowed to be multi-aggregated */
5516  if( SCIPvarDoNotMultaggr(var) )
5517  {
5518  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5519  goto TERMINATE;
5520  }
5521 
5522  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5523  * variable bound variable of another variable), we have to remove it from the other variables implications or
5524  * variable bounds
5525  */
5526  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5527  assert(var->vlbs == NULL);
5528  assert(var->vubs == NULL);
5529  assert(var->implics == NULL);
5530  assert(var->cliquelist == NULL);
5531 
5532  /* set the aggregated variable's objective value to 0.0 */
5533  obj = var->obj;
5534  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5535 
5536  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5537  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5538  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5539  * objective of this variable is set to zero
5540  */
5541  SCIPlpDecNLoosevars(lp);
5542 
5543  /* unlock all rounding locks */
5544  for( i = 0; i < NLOCKTYPES; i++ )
5545  {
5546  nlocksdown[i] = var->nlocksdown[i];
5547  nlocksup[i] = var->nlocksup[i];
5548 
5549  var->nlocksdown[i] = 0;
5550  var->nlocksup[i] = 0;
5551  }
5552 
5553  /* convert variable into multi-aggregated variable */
5554  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5555  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5556  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5557  var->data.multaggr.constant = tmpconstant;
5558  var->data.multaggr.nvars = ntmpvars;
5559  var->data.multaggr.varssize = ntmpvars;
5560 
5561  /* mark variable to be non-deletable */
5563 
5564  /* relock the variable, thus increasing the locks of the aggregation variables */
5565  for( i = 0; i < NLOCKTYPES; i++ )
5566  {
5567  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, (SCIP_LOCKTYPE) i, nlocksdown[i], nlocksup[i]) );
5568  }
5569 
5570  /* update flags and branching factors and priorities of aggregation variables;
5571  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5572  */
5573  branchfactor = var->branchfactor;
5574  branchpriority = var->branchpriority;
5575  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5576 
5577  for( v = 0; v < ntmpvars; ++v )
5578  {
5579  assert(tmpvars[v] != NULL);
5580  tmpvars[v]->removable &= var->removable;
5581  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5582  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5583 
5584  /* mark variable to be non-deletable */
5585  SCIPvarMarkNotDeletable(tmpvars[v]);
5586  }
5587  for( v = 0; v < ntmpvars; ++v )
5588  {
5589  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5590  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5591  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5592  {
5593  if( tmpscalars[v] >= 0.0 )
5594  {
5595  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5596  }
5597  else
5598  {
5599  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5600  }
5601  }
5602  }
5603  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5604  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5605 
5606  if( var->probindex != -1 )
5607  {
5608  /* inform problem about the variable's status change */
5609  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5610  }
5611 
5612  /* issue VARFIXED event */
5613  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5614 
5615  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5616  * variables and the problem's objective offset
5617  */
5618  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventfilter, eventqueue, obj) );
5619 
5620  *aggregated = TRUE;
5621 
5622  TERMINATE:
5623  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5624  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5625 
5626  break;
5627 
5628  case SCIP_VARSTATUS_COLUMN:
5629  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5630  return SCIP_INVALIDDATA;
5631 
5632  case SCIP_VARSTATUS_FIXED:
5633  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5634  return SCIP_INVALIDDATA;
5635 
5637  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5638  return SCIP_INVALIDDATA;
5639 
5641  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5642  return SCIP_INVALIDDATA;
5643 
5645  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5646  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5647  */
5648  assert(SCIPsetIsZero(set, var->obj));
5649  assert(var->negatedvar != NULL);
5651  assert(var->negatedvar->negatedvar == var);
5652 
5653  /* switch the signs of the aggregation scalars */
5654  for( v = 0; v < naggvars; ++v )
5655  scalars[v] *= -1.0;
5656 
5657  /* perform the multi aggregation on the negation variable */
5658  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5659  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5660  var->data.negate.constant - constant, infeasible, aggregated) );
5661 
5662  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5663  for( v = 0; v < naggvars; ++v )
5664  scalars[v] *= -1.0;
5665  break;
5666 
5667  default:
5668  SCIPerrorMessage("unknown variable status\n");
5669  return SCIP_INVALIDDATA;
5670  }
5671 
5672  return SCIP_OKAY;
5673 }
5674 
5675 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5676  * or for original variables the same variable is returned
5677  */
5678 static
5680  SCIP_VAR* var /**< problem variable */
5681  )
5682 {
5683  SCIP_VAR* retvar;
5684 
5685  assert(var != NULL);
5686 
5687  retvar = var;
5688 
5689  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5690 
5691  while( TRUE ) /*lint !e716 */
5692  {
5693  assert(retvar != NULL);
5694 
5695  switch( SCIPvarGetStatus(retvar) )
5696  {
5698  case SCIP_VARSTATUS_LOOSE:
5699  case SCIP_VARSTATUS_COLUMN:
5700  case SCIP_VARSTATUS_FIXED:
5701  return retvar;
5702 
5704  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5705  if ( retvar->data.multaggr.nvars == 1 )
5706  retvar = retvar->data.multaggr.vars[0];
5707  else
5708  return retvar;
5709  break;
5710 
5712  retvar = retvar->data.aggregate.var;
5713  break;
5714 
5716  retvar = retvar->negatedvar;
5717  break;
5718 
5719  default:
5720  SCIPerrorMessage("unknown variable status\n");
5721  SCIPABORT();
5722  return NULL; /*lint !e527*/
5723  }
5724  }
5725 }
5726 
5727 /** returns whether variable is not allowed to be multi-aggregated */
5729  SCIP_VAR* var /**< problem variable */
5730  )
5731 {
5732  SCIP_VAR* retvar;
5733 
5734  assert(var != NULL);
5735 
5736  retvar = varGetActiveVar(var);
5737  assert(retvar != NULL);
5738 
5739  switch( SCIPvarGetStatus(retvar) )
5740  {
5742  case SCIP_VARSTATUS_LOOSE:
5743  case SCIP_VARSTATUS_COLUMN:
5744  case SCIP_VARSTATUS_FIXED:
5745  return retvar->donotmultaggr;
5746 
5748  return FALSE;
5749 
5752  default:
5753  SCIPerrorMessage("wrong variable status\n");
5754  SCIPABORT();
5755  return FALSE; /*lint !e527 */
5756  }
5757 }
5758 
5759 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5760  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5761  * negated variable is created
5762  */
5764  SCIP_VAR* var, /**< problem variable to negate */
5765  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5766  SCIP_SET* set, /**< global SCIP settings */
5767  SCIP_STAT* stat, /**< problem statistics */
5768  SCIP_VAR** negvar /**< pointer to store the negated variable */
5769  )
5770 {
5771  assert(var != NULL);
5772  assert(var->scip == set->scip);
5773  assert(negvar != NULL);
5774 
5775  /* check, if we already created the negated variable */
5776  if( var->negatedvar == NULL )
5777  {
5778  char negvarname[SCIP_MAXSTRLEN];
5779 
5780  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5781 
5782  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5783 
5784  /* negation is only possible for bounded variables */
5785  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5786  {
5787  SCIPerrorMessage("cannot negate unbounded variable\n");
5788  return SCIP_INVALIDDATA;
5789  }
5790 
5791  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5792 
5793  /* create negated variable */
5794  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5795  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5796  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5797  if( SCIPvarIsBinary(var) )
5798  (*negvar)->data.negate.constant = 1.0;
5799  else
5800  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5801 
5802  /* create event filter for transformed variable */
5803  if( SCIPvarIsTransformed(var) )
5804  {
5805  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5806  }
5807 
5808  /* set the bounds corresponding to the negation variable */
5809  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5810  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5811  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5812  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5813  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5814 
5815  /* link the variables together */
5816  var->negatedvar = *negvar;
5817  (*negvar)->negatedvar = var;
5818 
5819  /* mark both variables to be non-deletable */
5821  SCIPvarMarkNotDeletable(*negvar);
5822 
5823  /* copy the branch factor and priority, and use the negative preferred branching direction */
5824  (*negvar)->branchfactor = var->branchfactor;
5825  (*negvar)->branchpriority = var->branchpriority;
5826  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5827 
5828  /* copy doNotMultiaggr status */
5829  (*negvar)->donotmultaggr = var->donotmultaggr;
5830 
5831  /* copy lazy bounds (they have to be flipped) */
5832  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5833  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5834 
5835  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5836  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5837  assert((*negvar)->nuses == 1);
5838  }
5839  assert(var->negatedvar != NULL);
5840 
5841  /* return the negated variable */
5842  *negvar = var->negatedvar;
5843 
5844  /* exactly one variable of the negation pair has to be marked as negated variable */
5846 
5847  return SCIP_OKAY;
5848 }
5849 
5850 /** informs variable that its position in problem's vars array changed */
5851 static
5852 void varSetProbindex(
5853  SCIP_VAR* var, /**< problem variable */
5854  int probindex /**< new problem index of variable (-1 for removal) */
5855  )
5856 {
5857  assert(var != NULL);
5858  assert(probindex >= 0 || var->vlbs == NULL);
5859  assert(probindex >= 0 || var->vubs == NULL);
5860  assert(probindex >= 0 || var->implics == NULL);
5861 
5862  var->probindex = probindex;
5864  {
5865  assert(var->data.col != NULL);
5866  var->data.col->var_probindex = probindex;
5867  }
5868 }
5869 
5870 /** informs variable that its position in problem's vars array changed */
5871 void SCIPvarSetProbindex(
5872  SCIP_VAR* var, /**< problem variable */
5873  int probindex /**< new problem index of variable */
5874  )
5875 {
5876  assert(var != NULL);
5877  assert(probindex >= 0);
5878 
5879  varSetProbindex(var, probindex);
5880 }
5881 
5882 /** gives the variable a new name
5883  *
5884  * @note the old pointer is overwritten, which might result in a memory leakage
5885  */
5887  SCIP_VAR* var, /**< problem variable */
5888  const char* name /**< new name of variable */
5889  )
5890 {
5891  assert(var != NULL);
5892  assert(name != NULL);
5893 
5894  var->name = (char*)name;
5895 }
5896 
5897 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5898  * implication graph;
5899  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5900  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5901  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5902  * than removing the variables one by one, each time updating all lists of the other variables.
5903  */
5905  SCIP_VAR* var, /**< problem variable */
5906  BMS_BLKMEM* blkmem, /**< block memory buffer */
5907  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5908  SCIP_SET* set, /**< global SCIP settings */
5909  SCIP_Bool final /**< is this the final removal of all problem variables? */
5910  )
5911 {
5912  assert(SCIPvarGetProbindex(var) >= 0);
5913  assert(var->scip == set->scip);
5914 
5915  /* if the variable is active in the transformed problem, remove it from the implication graph */
5916  if( SCIPvarIsTransformed(var)
5918  {
5919  if( final )
5920  {
5921  /* just destroy the data structures */
5922  SCIPvboundsFree(&var->vlbs, blkmem);
5923  SCIPvboundsFree(&var->vubs, blkmem);
5924  SCIPimplicsFree(&var->implics, blkmem);
5925  }
5926  else
5927  {
5928  /* unlink the variable from all other variables' lists and free the data structures */
5929  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5930  }
5931  }
5932 
5933  /* mark the variable to be no longer a member of the problem */
5934  varSetProbindex(var, -1);
5935 
5936  return SCIP_OKAY;
5937 }
5938 
5939 /** marks the variable to be deleted from the problem */
5940 void SCIPvarMarkDeleted(
5941  SCIP_VAR* var /**< problem variable */
5942  )
5943 {
5944  assert(var != NULL);
5945  assert(var->probindex != -1);
5946 
5947  var->deleted = TRUE;
5948 }
5949 
5950 /** marks the variable to not to be multi-aggregated */
5952  SCIP_VAR* var /**< problem variable */
5953  )
5954 {
5955  SCIP_VAR* retvar;
5956 
5957  assert(var != NULL);
5958 
5959  retvar = varGetActiveVar(var);
5960  assert(retvar != NULL);
5961 
5962  switch( SCIPvarGetStatus(retvar) )
5963  {
5965  case SCIP_VARSTATUS_LOOSE:
5966  case SCIP_VARSTATUS_COLUMN:
5967  case SCIP_VARSTATUS_FIXED:
5968  retvar->donotmultaggr = TRUE;
5969  break;
5970 
5972  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5973  return SCIP_INVALIDDATA;
5974 
5977  default:
5978  SCIPerrorMessage("wrong variable status\n");
5979  return SCIP_INVALIDDATA;
5980  }
5981 
5982  return SCIP_OKAY;
5983 }
5984 
5985 /** changes type of variable; cannot be called, if var belongs to a problem */
5987  SCIP_VAR* var, /**< problem variable to change */
5988  BMS_BLKMEM* blkmem, /**< block memory */
5989  SCIP_SET* set, /**< global SCIP settings */
5990  SCIP_PRIMAL* primal, /**< primal data */
5991  SCIP_LP* lp, /**< current LP data */
5992  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5993  SCIP_VARTYPE vartype /**< new type of variable */
5994  )
5995 {
5996  SCIP_EVENT* event;
5997  SCIP_VARTYPE oldtype;
5998 
5999  assert(var != NULL);
6000 
6001  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
6002 
6003  if( var->probindex >= 0 )
6004  {
6005  SCIPerrorMessage("cannot change type of variable already in the problem\n");
6006  return SCIP_INVALIDDATA;
6007  }
6008 
6009  oldtype = (SCIP_VARTYPE)var->vartype;
6010  var->vartype = vartype; /*lint !e641*/
6011 
6013  {
6014  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var, oldtype, vartype) );
6015  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6016  }
6017 
6018  if( var->negatedvar != NULL )
6019  {
6020  assert(oldtype == (SCIP_VARTYPE)var->negatedvar->vartype
6021  || SCIPvarIsBinary(var) == SCIPvarIsBinary(var->negatedvar));
6022 
6023 
6024  var->negatedvar->vartype = vartype; /*lint !e641*/
6025 
6027  {
6028  SCIP_CALL( SCIPeventCreateTypeChanged(&event, blkmem, var->negatedvar, oldtype, vartype) );
6029  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6030  }
6031  }
6032 
6033  return SCIP_OKAY;
6034 }
6035 
6036 /** appends OBJCHANGED event to the event queue */
6037 static
6039  SCIP_VAR* var, /**< problem variable to change */
6040  BMS_BLKMEM* blkmem, /**< block memory */
6041  SCIP_SET* set, /**< global SCIP settings */
6042  SCIP_PRIMAL* primal, /**< primal data */
6043  SCIP_LP* lp, /**< current LP data */
6044  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6045  SCIP_Real oldobj, /**< old objective value for variable */
6046  SCIP_Real newobj /**< new objective value for variable */
6047  )
6048 {
6049  SCIP_EVENT* event;
6050 
6051  assert(var != NULL);
6052  assert(var->scip == set->scip);
6053  assert(var->eventfilter != NULL);
6055  assert(SCIPvarIsTransformed(var));
6056 
6057  /* In the case where the objcetive value of a variable is very close to epsilon, and it is aggregated
6058  * into a variable with a big objective value, round-off errors might make the assert oldobj != newobj fail.
6059  * Hence, we relax it by letting it pass if the variables are percieved the same and we use very large values
6060  * that make comparison with values close to epsilon inaccurate.
6061  */
6062  assert(!SCIPsetIsEQ(set, oldobj, newobj) ||
6063  (SCIPsetIsEQ(set, oldobj, newobj) && REALABS(newobj) > 1e+15 * SCIPsetEpsilon(set))
6064  );
6065 
6066  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
6067  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
6068 
6069  return SCIP_OKAY;
6070 }
6071 
6072 /** changes objective value of variable */
6074  SCIP_VAR* var, /**< variable to change */
6075  BMS_BLKMEM* blkmem, /**< block memory */
6076  SCIP_SET* set, /**< global SCIP settings */
6077  SCIP_PROB* prob, /**< problem data */
6078  SCIP_PRIMAL* primal, /**< primal data */
6079  SCIP_LP* lp, /**< current LP data */
6080  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6081  SCIP_Real newobj /**< new objective value for variable */
6082  )
6083 {
6084  SCIP_Real oldobj;
6085 
6086  assert(var != NULL);
6087  assert(set != NULL);
6088  assert(var->scip == set->scip);
6089 
6090  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
6091 
6092  if( !SCIPsetIsEQ(set, var->obj, newobj) )
6093  {
6094  switch( SCIPvarGetStatus(var) )
6095  {
6097  if( var->data.original.transvar != NULL )
6098  {
6099  assert(SCIPprobIsTransformed(prob));
6100 
6101  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
6102  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
6103  }
6104  else
6105  assert(set->stage == SCIP_STAGE_PROBLEM);
6106 
6107  var->obj = newobj;
6108  var->unchangedobj = newobj;
6109 
6110  break;
6111 
6112  case SCIP_VARSTATUS_LOOSE:
6113  case SCIP_VARSTATUS_COLUMN:
6114  oldobj = var->obj;
6115  var->obj = newobj;
6116 
6117  /* update unchanged objective value of variable */
6118  if( !lp->divingobjchg )
6119  var->unchangedobj = newobj;
6120 
6121  /* update the number of variables with non-zero objective coefficient;
6122  * we only want to do the update, if the variable is added to the problem;
6123  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6124  */
6125  if( SCIPvarIsActive(var) )
6126  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
6127 
6128  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6129  break;
6130 
6131  case SCIP_VARSTATUS_FIXED:
6135  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
6136  return SCIP_INVALIDDATA;
6137 
6138  default:
6139  SCIPerrorMessage("unknown variable status\n");
6140  return SCIP_INVALIDDATA;
6141  }
6142  }
6143 
6144  return SCIP_OKAY;
6145 }
6146 
6147 /** adds value to objective value of variable */
6149  SCIP_VAR* var, /**< variable to change */
6150  BMS_BLKMEM* blkmem, /**< block memory */
6151  SCIP_SET* set, /**< global SCIP settings */
6152  SCIP_STAT* stat, /**< problem statistics */
6153  SCIP_PROB* transprob, /**< transformed problem data */
6154  SCIP_PROB* origprob, /**< original problem data */
6155  SCIP_PRIMAL* primal, /**< primal data */
6156  SCIP_TREE* tree, /**< branch and bound tree */
6157  SCIP_REOPT* reopt, /**< reoptimization data structure */
6158  SCIP_LP* lp, /**< current LP data */
6159  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
6160  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6161  SCIP_Real addobj /**< additional objective value for variable */
6162  )
6163 {
6164  assert(var != NULL);
6165  assert(set != NULL);
6166  assert(var->scip == set->scip);
6167  assert(set->stage < SCIP_STAGE_INITSOLVE);
6168 
6169  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
6170 
6171  if( !SCIPsetIsZero(set, addobj) )
6172  {
6173  SCIP_Real oldobj;
6174  int i;
6175 
6176  switch( SCIPvarGetStatus(var) )
6177  {
6179  if( var->data.original.transvar != NULL )
6180  {
6181  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6182  reopt, lp, eventfilter, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6183  }
6184  else
6185  assert(set->stage == SCIP_STAGE_PROBLEM);
6186 
6187  var->obj += addobj;
6188  var->unchangedobj += addobj;
6189  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6190 
6191  break;
6192 
6193  case SCIP_VARSTATUS_LOOSE:
6194  case SCIP_VARSTATUS_COLUMN:
6195  oldobj = var->obj;
6196  var->obj += addobj;
6197 
6198  /* update unchanged objective value of variable */
6199  if( !lp->divingobjchg )
6200  {
6201  var->unchangedobj += addobj;
6202  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6203  }
6204 
6205  /* update the number of variables with non-zero objective coefficient;
6206  * we only want to do the update, if the variable is added to the problem;
6207  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6208  */
6209  if( SCIPvarIsActive(var) )
6210  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6211 
6212  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6213  break;
6214 
6215  case SCIP_VARSTATUS_FIXED:
6216  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6217  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6218  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6219  break;
6220 
6222  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6223  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6224  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6225  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6226  lp, eventfilter, eventqueue, var->data.aggregate.scalar * addobj) );
6227  break;
6228 
6230  assert(!var->donotmultaggr);
6231  /* 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 */
6232  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6233  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6234  for( i = 0; i < var->data.multaggr.nvars; ++i )
6235  {
6236  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6237  reopt, lp, eventfilter, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6238  }
6239  break;
6240 
6242  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6243  assert(var->negatedvar != NULL);
6245  assert(var->negatedvar->negatedvar == var);
6246  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6247  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventfilter, eventqueue, transprob, origprob, tree, reopt, lp) );
6248  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6249  eventfilter, eventqueue, -addobj) );
6250  break;
6251 
6252  default:
6253  SCIPerrorMessage("unknown variable status\n");
6254  return SCIP_INVALIDDATA;
6255  }
6256  }
6257 
6258  return SCIP_OKAY;
6259 }
6260 
6261 /** changes objective value of variable in current dive */
6263  SCIP_VAR* var, /**< problem variable to change */
6264  SCIP_SET* set, /**< global SCIP settings */
6265  SCIP_LP* lp, /**< current LP data */
6266  SCIP_Real newobj /**< new objective value for variable */
6267  )
6268 {
6269  assert(var != NULL);
6270  assert(set != NULL);
6271  assert(var->scip == set->scip);
6272  assert(lp != NULL);
6273 
6274  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6275 
6276  if( SCIPsetIsZero(set, newobj) )
6277  newobj = 0.0;
6278 
6279  /* change objective value of attached variables */
6280  switch( SCIPvarGetStatus(var) )
6281  {
6283  assert(var->data.original.transvar != NULL);
6284  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6285  break;
6286 
6287  case SCIP_VARSTATUS_COLUMN:
6288  assert(var->data.col != NULL);
6289  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6290  break;
6291 
6292  case SCIP_VARSTATUS_LOOSE:
6293  case SCIP_VARSTATUS_FIXED:
6294  /* nothing to do here: only the constant shift in objective function would change */
6295  break;
6296 
6297  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6298  assert(var->data.aggregate.var != NULL);
6299  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6300  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6301  /* the constant can be ignored, because it would only affect the objective shift */
6302  break;
6303 
6305  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6306  return SCIP_INVALIDDATA;
6307 
6308  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6309  assert(var->negatedvar != NULL);
6311  assert(var->negatedvar->negatedvar == var);
6312  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6313  /* the offset can be ignored, because it would only affect the objective shift */
6314  break;
6315 
6316  default:
6317  SCIPerrorMessage("unknown variable status\n");
6318  return SCIP_INVALIDDATA;
6319  }
6320 
6321  return SCIP_OKAY;
6322 }
6323 
6324 /** adjust lower bound to integral value, if variable is integral */
6325 void SCIPvarAdjustLb(
6326  SCIP_VAR* var, /**< problem variable */
6327  SCIP_SET* set, /**< global SCIP settings */
6328  SCIP_Real* lb /**< pointer to lower bound to adjust */
6329  )
6330 {
6331  assert(var != NULL);
6332  assert(set != NULL);
6333  assert(var->scip == set->scip);
6334  assert(lb != NULL);
6335 
6336  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6337 
6338  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6339 }
6340 
6341 /** adjust upper bound to integral value, if variable is integral */
6342 void SCIPvarAdjustUb(
6343  SCIP_VAR* var, /**< problem variable */
6344  SCIP_SET* set, /**< global SCIP settings */
6345  SCIP_Real* ub /**< pointer to upper bound to adjust */
6346  )
6347 {
6348  assert(var != NULL);
6349  assert(set != NULL);
6350  assert(var->scip == set->scip);
6351  assert(ub != NULL);
6352 
6353  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6354 
6355  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6356 }
6357 
6358 /** adjust lower or upper bound to integral value, if variable is integral */
6359 void SCIPvarAdjustBd(
6360  SCIP_VAR* var, /**< problem variable */
6361  SCIP_SET* set, /**< global SCIP settings */
6362  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6363  SCIP_Real* bd /**< pointer to bound to adjust */
6364  )
6365 {
6366  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6367 
6368  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6369  SCIPvarAdjustLb(var, set, bd);
6370  else
6371  SCIPvarAdjustUb(var, set, bd);
6372 }
6373 
6374 /** changes lower bound of original variable in original problem */
6376  SCIP_VAR* var, /**< problem variable to change */
6377  SCIP_SET* set, /**< global SCIP settings */
6378  SCIP_Real newbound /**< new bound for variable */
6379  )
6380 {
6381  int i;
6382 
6383  assert(var != NULL);
6384  assert(!SCIPvarIsTransformed(var));
6386  assert(set != NULL);
6387  assert(var->scip == set->scip);
6388  assert(set->stage == SCIP_STAGE_PROBLEM);
6389 
6390  /* check that the bound is feasible */
6391  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6392  /* adjust bound to integral value if variable is of integral type */
6393  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6394 
6395  if( SCIPsetIsZero(set, newbound) )
6396  newbound = 0.0;
6397 
6398  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6400  {
6401  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6402  var->name, var->data.original.origdom.lb, newbound);
6403 
6404  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6405  return SCIP_OKAY;
6406 
6407  /* change the bound */
6408  var->data.original.origdom.lb = newbound;
6409  }
6410  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6411  {
6412  assert( var->negatedvar != NULL );
6413  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6414  }
6415 
6416  /* process parent variables */
6417  for( i = 0; i < var->nparentvars; ++i )
6418  {
6419  SCIP_VAR* parentvar;
6420 
6421  parentvar = var->parentvars[i];
6422  assert(parentvar != NULL);
6423  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6424  assert(parentvar->negatedvar == var);
6425  assert(var->negatedvar == parentvar);
6426 
6427  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6428  }
6429 
6430  return SCIP_OKAY;
6431 }
6432 
6433 /** changes upper bound of original variable in original problem */
6435  SCIP_VAR* var, /**< problem variable to change */
6436  SCIP_SET* set, /**< global SCIP settings */
6437  SCIP_Real newbound /**< new bound for variable */
6438  )
6439 {
6440  int i;
6441 
6442  assert(var != NULL);
6443  assert(!SCIPvarIsTransformed(var));
6445  assert(set != NULL);
6446  assert(var->scip == set->scip);
6447  assert(set->stage == SCIP_STAGE_PROBLEM);
6448 
6449  /* check that the bound is feasible */
6450  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6451  /* adjust bound to integral value if variable is of integral type */
6452  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6453 
6454  if( SCIPsetIsZero(set, newbound) )
6455  newbound = 0.0;
6456 
6457  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6459  {
6460  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6461  var->name, var->data.original.origdom.ub, newbound);
6462 
6463  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6464  return SCIP_OKAY;
6465 
6466  /* change the bound */
6467  var->data.original.origdom.ub = newbound;
6468  }
6469  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6470  {
6471  assert( var->negatedvar != NULL );
6472  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6473  }
6474 
6475  /* process parent variables */
6476  for( i = 0; i < var->nparentvars; ++i )
6477  {
6478  SCIP_VAR* parentvar;
6479 
6480  parentvar = var->parentvars[i];
6481  assert(parentvar != NULL);
6482  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6483  assert(parentvar->negatedvar == var);
6484  assert(var->negatedvar == parentvar);
6485 
6486  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6487  }
6488 
6489  return SCIP_OKAY;
6490 }
6491 
6492 /** appends GLBCHANGED event to the event queue */
6493 static
6495  SCIP_VAR* var, /**< problem variable to change */
6496  BMS_BLKMEM* blkmem, /**< block memory */
6497  SCIP_SET* set, /**< global SCIP settings */
6498  SCIP_LP* lp, /**< current LP data */
6499  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6500  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6501  SCIP_Real oldbound, /**< old lower bound for variable */
6502  SCIP_Real newbound /**< new lower bound for variable */
6503  )
6504 {
6505  assert(var != NULL);
6506  assert(var->eventfilter != NULL);
6507  assert(SCIPvarIsTransformed(var));
6508  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6509  assert(set != NULL);
6510  assert(var->scip == set->scip);
6511 
6512  /* check, if the variable is being tracked for bound changes
6513  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6514  */
6515  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6518  {
6519  SCIP_EVENT* event;
6520 
6521  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6522 
6523  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6524  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6525  }
6526 
6527  return SCIP_OKAY;
6528 }
6529 
6530 /** appends GUBCHANGED event to the event queue */
6531 static
6533  SCIP_VAR* var, /**< problem variable to change */
6534  BMS_BLKMEM* blkmem, /**< block memory */
6535  SCIP_SET* set, /**< global SCIP settings */
6536  SCIP_LP* lp, /**< current LP data */
6537  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6538  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6539  SCIP_Real oldbound, /**< old lower bound for variable */
6540  SCIP_Real newbound /**< new lower bound for variable */
6541  )
6542 {
6543  assert(var != NULL);
6544  assert(var->eventfilter != NULL);
6545  assert(SCIPvarIsTransformed(var));
6546  assert(!SCIPsetIsEQ(set, oldbound, newbound) || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
6547  assert(set != NULL);
6548  assert(var->scip == set->scip);
6549 
6550  /* check, if the variable is being tracked for bound changes
6551  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6552  */
6553  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6556  {
6557  SCIP_EVENT* event;
6558 
6559  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6560 
6561  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6562  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6563  }
6564 
6565  return SCIP_OKAY;
6566 }
6567 
6568 /** appends GHOLEADDED event to the event queue */
6569 static
6571  SCIP_VAR* var, /**< problem variable to change */
6572  BMS_BLKMEM* blkmem, /**< block memory */
6573  SCIP_SET* set, /**< global SCIP settings */
6574  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6575  SCIP_Real left, /**< left bound of open interval in new hole */
6576  SCIP_Real right /**< right bound of open interval in new hole */
6577  )
6578 {
6579  assert(var != NULL);
6580  assert(var->eventfilter != NULL);
6581  assert(SCIPvarIsTransformed(var));
6582  assert(set != NULL);
6583  assert(var->scip == set->scip);
6584  assert(SCIPsetIsLT(set, left, right));
6585 
6586  /* check, if the variable is being tracked for bound changes */
6587  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6588  {
6589  SCIP_EVENT* event;
6590 
6591  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6592 
6593  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6594  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6595  }
6596 
6597  return SCIP_OKAY;
6598 }
6599 
6600 /** increases root bound change statistics after a global bound change */
6601 static
6602 void varIncRootboundchgs(
6603  SCIP_VAR* var, /**< problem variable to change */
6604  SCIP_SET* set, /**< global SCIP settings */
6605  SCIP_STAT* stat /**< problem statistics */
6606  )
6607 {
6608  assert(var != NULL);
6609  assert(set != NULL);
6610  assert(var->scip == set->scip);
6611  assert(stat != NULL);
6612 
6613  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6614  {
6615  stat->nrootboundchgs++;
6616  stat->nrootboundchgsrun++;
6617  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6618  {
6619  stat->nrootintfixings++;
6620  stat->nrootintfixingsrun++;
6621  }
6622  }
6623 }
6624 
6625 /* forward declaration, because both methods call each other recursively */
6626 
6627 /* performs the current change in upper bound, changes all parents accordingly */
6628 static
6630  SCIP_VAR* var, /**< problem variable to change */
6631  BMS_BLKMEM* blkmem, /**< block memory */
6632  SCIP_SET* set, /**< global SCIP settings */
6633  SCIP_STAT* stat, /**< problem statistics */
6634  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6635  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6636  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6637  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6638  SCIP_Real newbound /**< new bound for variable */
6639  );
6640 
6641 /** performs the current change in lower bound, changes all parents accordingly */
6642 static
6644  SCIP_VAR* var, /**< problem variable to change */
6645  BMS_BLKMEM* blkmem, /**< block memory */
6646  SCIP_SET* set, /**< global SCIP settings */
6647  SCIP_STAT* stat, /**< problem statistics */
6648  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6649  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6650  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6651  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6652  SCIP_Real newbound /**< new bound for variable */
6653  )
6654 {
6655  SCIP_VAR* parentvar;
6656  SCIP_Real oldbound;
6657  int i;
6658 
6659  assert(var != NULL);
6660  /* local domains can violate global bounds but not more than feasibility epsilon */
6661  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6662  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6663  assert(blkmem != NULL);
6664  assert(set != NULL);
6665  assert(var->scip == set->scip);
6666  assert(stat != NULL);
6667 
6668  /* adjust bound to integral value if variable is of integral type */
6669  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6670 
6671  /* check that the bound is feasible */
6672  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6673  {
6674  /* due to numerics we only want to be feasible in feasibility tolerance */
6675  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6676  newbound = var->glbdom.ub;
6677  }
6678  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6679 
6680  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6681 
6682  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6683 
6684  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
6685  return SCIP_OKAY;
6686 
6687  /* check bound on debugging solution */
6688  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6689 
6690  /* change the bound */
6691  oldbound = var->glbdom.lb;
6692  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6693  var->glbdom.lb = newbound;
6694  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6695  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6696 
6697  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6698  {
6699  /* merges overlapping holes into single holes, moves bounds respectively */
6700  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6701  }
6702 
6703  /* update the root bound changes counters */
6704  varIncRootboundchgs(var, set, stat);
6705 
6706  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6707  * redundant bound changes to be branching decisions
6708  */
6709  for( i = 0; i < var->nlbchginfos; ++i )
6710  {
6711  assert(var->lbchginfos[i].var == var);
6712 
6713  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6714  {
6715  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6716  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6717  var->lbchginfos[i].oldbound = var->glbdom.lb;
6718  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6719  {
6720  /* this bound change is redundant due to the new global bound */
6721  var->lbchginfos[i].newbound = var->glbdom.lb;
6722  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6723  var->lbchginfos[i].redundant = TRUE;
6724  }
6725  else
6726  break; /* from now on, the remaining local bound changes are not redundant */
6727  }
6728  else
6729  break; /* from now on, the remaining local bound changes are not redundant */
6730  }
6731 
6732  /* remove redundant implications and variable bounds */
6734  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6735  {
6736  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6737  }
6738 
6739  /* issue bound change event */
6740  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6741  if( var->eventfilter != NULL )
6742  {
6743  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6744  }
6745 
6746  /* process parent variables */
6747  for( i = 0; i < var->nparentvars; ++i )
6748  {
6749  parentvar = var->parentvars[i];
6750  assert(parentvar != NULL);
6751 
6752  switch( SCIPvarGetStatus(parentvar) )
6753  {
6755  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6756  break;
6757 
6758  case SCIP_VARSTATUS_COLUMN:
6759  case SCIP_VARSTATUS_LOOSE:
6760  case SCIP_VARSTATUS_FIXED:
6762  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6763  return SCIP_INVALIDDATA;
6764 
6765  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6766  assert(parentvar->data.aggregate.var == var);
6767  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6768  {
6769  SCIP_Real parentnewbound;
6770 
6771  /* a > 0 -> change lower bound of y */
6772  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, -oldbound)
6773  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6774  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6775 
6776  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6777  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6778  else
6779  parentnewbound = newbound;
6780  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6781  }
6782  else
6783  {
6784  SCIP_Real parentnewbound;
6785 
6786  /* a < 0 -> change upper bound of y */
6787  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6788  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, -oldbound)
6789  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6790  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6791 
6792  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6793  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6794  else
6795  parentnewbound = -newbound;
6796  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6797  }
6798  break;
6799 
6800  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6801  assert(parentvar->negatedvar != NULL);
6802  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6803  assert(parentvar->negatedvar->negatedvar == parentvar);
6804  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6805  parentvar->data.negate.constant - newbound) );
6806  break;
6807 
6808  default:
6809  SCIPerrorMessage("unknown variable status\n");
6810  return SCIP_INVALIDDATA;
6811  }
6812  }
6813 
6814  return SCIP_OKAY;
6815 }
6816 
6817 /** performs the current change in upper bound, changes all parents accordingly */
6818 static
6820  SCIP_VAR* var, /**< problem variable to change */
6821  BMS_BLKMEM* blkmem, /**< block memory */
6822  SCIP_SET* set, /**< global SCIP settings */
6823  SCIP_STAT* stat, /**< problem statistics */
6824  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6825  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6826  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6827  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6828  SCIP_Real newbound /**< new bound for variable */
6829  )
6830 {
6831  SCIP_VAR* parentvar;
6832  SCIP_Real oldbound;
6833  int i;
6834 
6835  assert(var != NULL);
6836  /* local domains can violate global bounds but not more than feasibility epsilon */
6837  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6838  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6839  assert(blkmem != NULL);
6840  assert(set != NULL);
6841  assert(var->scip == set->scip);
6842  assert(stat != NULL);
6843 
6844  /* adjust bound to integral value if variable is of integral type */
6845  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6846 
6847  /* check that the bound is feasible */
6848  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6849  {
6850  /* due to numerics we only want to be feasible in feasibility tolerance */
6851  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6852  newbound = var->glbdom.lb;
6853  }
6854  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6855 
6856  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6857 
6858  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6859 
6860  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
6861  return SCIP_OKAY;
6862 
6863  /* check bound on debugging solution */
6864  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6865 
6866  /* change the bound */
6867  oldbound = var->glbdom.ub;
6868  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6869  var->glbdom.ub = newbound;
6870  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6871  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6872 
6873  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6874  {
6875  /* merges overlapping holes into single holes, moves bounds respectively */
6876  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6877  }
6878 
6879  /* update the root bound changes counters */
6880  varIncRootboundchgs(var, set, stat);
6881 
6882  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6883  * redundant bound changes to be branching decisions
6884  */
6885  for( i = 0; i < var->nubchginfos; ++i )
6886  {
6887  assert(var->ubchginfos[i].var == var);
6888  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6889  {
6890  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6891  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6892  var->ubchginfos[i].oldbound = var->glbdom.ub;
6893  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6894  {
6895  /* this bound change is redundant due to the new global bound */
6896  var->ubchginfos[i].newbound = var->glbdom.ub;
6897  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6898  var->ubchginfos[i].redundant = TRUE;
6899  }
6900  else
6901  break; /* from now on, the remaining local bound changes are not redundant */
6902  }
6903  else
6904  break; /* from now on, the remaining local bound changes are not redundant */
6905  }
6906 
6907  /* remove redundant implications and variable bounds */
6909  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6910  {
6911  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6912  }
6913 
6914  /* issue bound change event */
6915  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6916  if( var->eventfilter != NULL )
6917  {
6918  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6919  }
6920 
6921  /* process parent variables */
6922  for( i = 0; i < var->nparentvars; ++i )
6923  {
6924  parentvar = var->parentvars[i];
6925  assert(parentvar != NULL);
6926 
6927  switch( SCIPvarGetStatus(parentvar) )
6928  {
6930  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6931  break;
6932 
6933  case SCIP_VARSTATUS_COLUMN:
6934  case SCIP_VARSTATUS_LOOSE:
6935  case SCIP_VARSTATUS_FIXED:
6937  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6938  return SCIP_INVALIDDATA;
6939 
6940  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6941  assert(parentvar->data.aggregate.var == var);
6942  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6943  {
6944  SCIP_Real parentnewbound;
6945 
6946  /* a > 0 -> change upper bound of y */
6947  assert(SCIPsetIsInfinity(set, parentvar->glbdom.ub) || SCIPsetIsInfinity(set, oldbound)
6948  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6949  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6950  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6951  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6952  else
6953  parentnewbound = newbound;
6954  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6955  }
6956  else
6957  {
6958  SCIP_Real parentnewbound;
6959 
6960  /* a < 0 -> change lower bound of y */
6961  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6962  assert(SCIPsetIsInfinity(set, -parentvar->glbdom.lb) || SCIPsetIsInfinity(set, oldbound)
6963  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6964  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6965  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6966  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6967  else
6968  parentnewbound = -newbound;
6969  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6970  }
6971  break;
6972 
6973  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6974  assert(parentvar->negatedvar != NULL);
6975  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6976  assert(parentvar->negatedvar->negatedvar == parentvar);
6977  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6978  parentvar->data.negate.constant - newbound) );
6979  break;
6980 
6981  default:
6982  SCIPerrorMessage("unknown variable status\n");
6983  return SCIP_INVALIDDATA;
6984  }
6985  }
6986 
6987  return SCIP_OKAY;
6988 }
6989 
6990 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6991  * updates local lower bound if the global bound is tighter
6992  */
6994  SCIP_VAR* var, /**< problem variable to change */
6995  BMS_BLKMEM* blkmem, /**< block memory */
6996  SCIP_SET* set, /**< global SCIP settings */
6997  SCIP_STAT* stat, /**< problem statistics */
6998  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6999  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7000  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7001  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7002  SCIP_Real newbound /**< new bound for variable */
7003  )
7004 {
7005  assert(var != NULL);
7006  assert(blkmem != NULL);
7007  assert(set != NULL);
7008  assert(var->scip == set->scip);
7009 
7010  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7011  * of the domain within feastol
7012  */
7013  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7014 
7015  /* adjust bound to integral value if variable is of integral type */
7016  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7017 
7018  /* check that the adjusted bound is feasible
7019  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7020  * here because we reset bounds to their original value!
7021  */
7022  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
7023 
7024  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7025  {
7026  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7027  newbound = MIN(newbound, var->glbdom.ub);
7028  }
7029  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7030 
7031  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7032  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7033  */
7034  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7035 
7036  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
7037 
7038  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) && !(newbound != var->glbdom.lb && newbound * var->glbdom.lb <= 0.0) ) /*lint !e777*/
7039  return SCIP_OKAY;
7040 
7041  /* change bounds of attached variables */
7042  switch( SCIPvarGetStatus(var) )
7043  {
7045  if( var->data.original.transvar != NULL )
7046  {
7047  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7048  cliquetable, newbound) );
7049  }
7050  else
7051  {
7052  assert(set->stage == SCIP_STAGE_PROBLEM);
7053  if( newbound > SCIPvarGetLbLocal(var) )
7054  {
7055  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7056  }
7057  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7058  }
7059  break;
7060 
7061  case SCIP_VARSTATUS_COLUMN:
7062  case SCIP_VARSTATUS_LOOSE:
7063  if( newbound > SCIPvarGetLbLocal(var) )
7064  {
7065  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7066  }
7067  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7068  break;
7069 
7070  case SCIP_VARSTATUS_FIXED:
7071  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7072  return SCIP_INVALIDDATA;
7073 
7074  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7075  assert(var->data.aggregate.var != NULL);
7076  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7077  {
7078  SCIP_Real childnewbound;
7079 
7080  /* a > 0 -> change lower bound of y */
7081  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7082  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7084  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7085  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7086  else
7087  childnewbound = newbound;
7088  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7089  childnewbound) );
7090  }
7091  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7092  {
7093  SCIP_Real childnewbound;
7094 
7095  /* a < 0 -> change upper bound of y */
7096  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7097  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
7099  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7100  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7101  else
7102  childnewbound = -newbound;
7103  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7104  childnewbound) );
7105  }
7106  else
7107  {
7108  SCIPerrorMessage("scalar is zero in aggregation\n");
7109  return SCIP_INVALIDDATA;
7110  }
7111  break;
7112 
7114  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7115  return SCIP_INVALIDDATA;
7116 
7117  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7118  assert(var->negatedvar != NULL);
7120  assert(var->negatedvar->negatedvar == var);
7121  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7122  var->data.negate.constant - newbound) );
7123  break;
7124 
7125  default:
7126  SCIPerrorMessage("unknown variable status\n");
7127  return SCIP_INVALIDDATA;
7128  }
7129 
7130  return SCIP_OKAY;
7131 }
7132 
7133 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
7134  * updates local upper bound if the global bound is tighter
7135  */
7137  SCIP_VAR* var, /**< problem variable to change */
7138  BMS_BLKMEM* blkmem, /**< block memory */
7139  SCIP_SET* set, /**< global SCIP settings */
7140  SCIP_STAT* stat, /**< problem statistics */
7141  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7142  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7143  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7144  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7145  SCIP_Real newbound /**< new bound for variable */
7146  )
7147 {
7148  assert(var != NULL);
7149  assert(blkmem != NULL);
7150  assert(set != NULL);
7151  assert(var->scip == set->scip);
7152 
7153  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7154  * of the domain within feastol
7155  */
7156  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7157 
7158  /* adjust bound to integral value if variable is of integral type */
7159  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7160 
7161  /* check that the adjusted bound is feasible
7162  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
7163  * here because we reset bounds to their original value!
7164  */
7165  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
7166 
7167  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7168  {
7169  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7170  newbound = MAX(newbound, var->glbdom.lb);
7171  }
7172  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7173 
7174  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7175  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7176  */
7177  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7178 
7179  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7180 
7181  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) && !(newbound != var->glbdom.ub && newbound * var->glbdom.ub <= 0.0) ) /*lint !e777*/
7182  return SCIP_OKAY;
7183 
7184  /* change bounds of attached variables */
7185  switch( SCIPvarGetStatus(var) )
7186  {
7188  if( var->data.original.transvar != NULL )
7189  {
7190  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7191  newbound) );
7192  }
7193  else
7194  {
7195  assert(set->stage == SCIP_STAGE_PROBLEM);
7196  if( newbound < SCIPvarGetUbLocal(var) )
7197  {
7198  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7199  }
7200  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7201  }
7202  break;
7203 
7204  case SCIP_VARSTATUS_COLUMN:
7205  case SCIP_VARSTATUS_LOOSE:
7206  if( newbound < SCIPvarGetUbLocal(var) )
7207  {
7208  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7209  }
7210  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7211  break;
7212 
7213  case SCIP_VARSTATUS_FIXED:
7214  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7215  return SCIP_INVALIDDATA;
7216 
7217  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7218  assert(var->data.aggregate.var != NULL);
7219  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7220  {
7221  SCIP_Real childnewbound;
7222 
7223  /* a > 0 -> change lower bound of y */
7224  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7225  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7227  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7228  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7229  else
7230  childnewbound = newbound;
7231  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7232  childnewbound) );
7233  }
7234  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7235  {
7236  SCIP_Real childnewbound;
7237 
7238  /* a < 0 -> change upper bound of y */
7239  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7240  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7242  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7243  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7244  else
7245  childnewbound = -newbound;
7246  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7247  childnewbound) );
7248  }
7249  else
7250  {
7251  SCIPerrorMessage("scalar is zero in aggregation\n");
7252  return SCIP_INVALIDDATA;
7253  }
7254  break;
7255 
7257  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7258  return SCIP_INVALIDDATA;
7259 
7260  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7261  assert(var->negatedvar != NULL);
7263  assert(var->negatedvar->negatedvar == var);
7264  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7265  var->data.negate.constant - newbound) );
7266  break;
7267 
7268  default:
7269  SCIPerrorMessage("unknown variable status\n");
7270  return SCIP_INVALIDDATA;
7271  }
7272 
7273  return SCIP_OKAY;
7274 }
7275 
7276 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7278  SCIP_VAR* var, /**< problem variable */
7279  SCIP_SET* set, /**< global SCIP settings */
7280  SCIP_Real lazylb /**< the lazy lower bound to be set */
7281  )
7282 {
7283  assert(var != NULL);
7284  assert(var->probindex != -1);
7285  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7286  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7287  assert(set != NULL);
7288  assert(var->scip == set->scip);
7289 
7290  /* variable should not be in the LP */
7292  return SCIP_INVALIDCALL;
7293 
7294  var->lazylb = lazylb;
7295 
7296  return SCIP_OKAY;
7297 }
7298 
7299 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7301  SCIP_VAR* var, /**< problem variable */
7302  SCIP_SET* set, /**< global SCIP settings */
7303  SCIP_Real lazyub /**< the lazy lower bound to be set */
7304  )
7305 {
7306  assert(var != NULL);
7307  assert(var->probindex != -1);
7308  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7309  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7310  assert(set != NULL);
7311  assert(var->scip == set->scip);
7312 
7313  /* variable should not be in the LP */
7315  return SCIP_INVALIDCALL;
7316 
7317  var->lazyub = lazyub;
7318 
7319  return SCIP_OKAY;
7320 }
7321 
7322 
7323 /** changes global bound of variable; if possible, adjusts bound to integral value;
7324  * updates local bound if the global bound is tighter
7325  */
7327  SCIP_VAR* var, /**< problem variable to change */
7328  BMS_BLKMEM* blkmem, /**< block memory */
7329  SCIP_SET* set, /**< global SCIP settings */
7330  SCIP_STAT* stat, /**< problem statistics */
7331  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7332  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7333  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7334  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7335  SCIP_Real newbound, /**< new bound for variable */
7336  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7337  )
7338 {
7339  /* apply bound change to the LP data */
7340  switch( boundtype )
7341  {
7342  case SCIP_BOUNDTYPE_LOWER:
7343  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7344  case SCIP_BOUNDTYPE_UPPER:
7345  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7346  default:
7347  SCIPerrorMessage("unknown bound type\n");
7348  return SCIP_INVALIDDATA;
7349  }
7350 }
7351 
7352 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7353 static
7355  SCIP_VAR* var, /**< problem variable to change */
7356  BMS_BLKMEM* blkmem, /**< block memory */
7357  SCIP_SET* set, /**< global SCIP settings */
7358  SCIP_LP* lp, /**< current LP data */
7359  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7360  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7361  SCIP_Real oldbound, /**< old lower bound for variable */
7362  SCIP_Real newbound /**< new lower bound for variable */
7363  )
7364 {
7365  assert(var != NULL);
7366  assert(var->eventfilter != NULL);
7367  assert(SCIPvarIsTransformed(var));
7368  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7369  assert(set != NULL);
7370  assert(var->scip == set->scip);
7371 
7372  /* check, if the variable is being tracked for bound changes
7373  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7374  */
7375  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7378  {
7379  SCIP_EVENT* event;
7380 
7381  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7382 
7383  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7384  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7385  }
7386 
7387  return SCIP_OKAY;
7388 }
7389 
7390 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7391 static
7393  SCIP_VAR* var, /**< problem variable to change */
7394  BMS_BLKMEM* blkmem, /**< block memory */
7395  SCIP_SET* set, /**< global SCIP settings */
7396  SCIP_LP* lp, /**< current LP data */
7397  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7398  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7399  SCIP_Real oldbound, /**< old upper bound for variable */
7400  SCIP_Real newbound /**< new upper bound for variable */
7401  )
7402 {
7403  assert(var != NULL);
7404  assert(var->eventfilter != NULL);
7405  assert(SCIPvarIsTransformed(var));
7406  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub || (newbound != oldbound && newbound * oldbound <= 0.0)); /*lint !e777*/
7407  assert(set != NULL);
7408  assert(var->scip == set->scip);
7409 
7410  /* check, if the variable is being tracked for bound changes
7411  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7412  */
7413  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7416  {
7417  SCIP_EVENT* event;
7418 
7419  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7420 
7421  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7422  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7423  }
7424 
7425  return SCIP_OKAY;
7426 }
7427 
7428 /* forward declaration, because both methods call each other recursively */
7429 
7430 /* performs the current change in upper bound, changes all parents accordingly */
7431 static
7433  SCIP_VAR* var, /**< problem variable to change */
7434  BMS_BLKMEM* blkmem, /**< block memory */
7435  SCIP_SET* set, /**< global SCIP settings */
7436  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7437  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7438  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7439  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7440  SCIP_Real newbound /**< new bound for variable */
7441  );
7442 
7443 /** performs the current change in lower bound, changes all parents accordingly */
7444 static
7446  SCIP_VAR* var, /**< problem variable to change */
7447  BMS_BLKMEM* blkmem, /**< block memory */
7448  SCIP_SET* set, /**< global SCIP settings */
7449  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7450  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7451  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7452  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7453  SCIP_Real newbound /**< new bound for variable */
7454  )
7455 {
7456  SCIP_VAR* parentvar;
7457  SCIP_Real oldbound;
7458  int i;
7459 
7460  assert(var != NULL);
7461  assert(set != NULL);
7462  assert(var->scip == set->scip);
7463  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7464  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7465  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7466  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7468 
7469  /* check that the bound is feasible */
7470  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7471  /* adjust bound to integral value if variable is of integral type */
7472  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7473 
7474  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7475  {
7476  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7477  newbound = MIN(newbound, var->locdom.ub);
7478 
7479  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7480  newbound = MAX(newbound, var->glbdom.lb);
7481  }
7482  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7483 
7484  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7485 
7486  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7487  newbound = var->glbdom.lb;
7488  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7489  return SCIP_OKAY;
7490 
7491  /* change the bound */
7492  oldbound = var->locdom.lb;
7493  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7494  var->locdom.lb = newbound;
7495 
7496  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7497  * once update the statistic
7498  */
7499  if( stat != NULL )
7500  SCIPstatIncrement(stat, set, domchgcount);
7501 
7502  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7503  {
7504  /* merges overlapping holes into single holes, moves bounds respectively */
7505  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7506  }
7507 
7508  /* issue bound change event */
7509  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7510  if( var->eventfilter != NULL )
7511  {
7512  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7513  }
7514 
7515  /* process parent variables */
7516  for( i = 0; i < var->nparentvars; ++i )
7517  {
7518  parentvar = var->parentvars[i];
7519  assert(parentvar != NULL);
7520 
7521  switch( SCIPvarGetStatus(parentvar) )
7522  {
7524  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7525  break;
7526 
7527  case SCIP_VARSTATUS_COLUMN:
7528  case SCIP_VARSTATUS_LOOSE:
7529  case SCIP_VARSTATUS_FIXED:
7531  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7532  return SCIP_INVALIDDATA;
7533 
7534  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7535  assert(parentvar->data.aggregate.var == var);
7536  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7537  {
7538  SCIP_Real parentnewbound;
7539 
7540  /* a > 0 -> change lower bound of y */
7541  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, -oldbound)
7542  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7543  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7544 
7545  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7546  {
7547  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7548  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7549  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7550  * as a result, the parent's lower bound is set to it's upper bound, and not above
7551  */
7552  if( parentnewbound > parentvar->glbdom.ub )
7553  {
7554  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7555  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7556  parentnewbound = parentvar->glbdom.ub;
7557  }
7558  }
7559  else
7560  parentnewbound = newbound;
7561  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7562  }
7563  else
7564  {
7565  SCIP_Real parentnewbound;
7566 
7567  /* a < 0 -> change upper bound of y */
7568  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7569  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, -oldbound)
7570  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7571  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7572 
7573  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7574  {
7575  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7576  /* 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
7577  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7578  * as a result, the parent's upper bound is set to it's lower bound, and not below
7579  */
7580  if( parentnewbound < parentvar->glbdom.lb )
7581  {
7582  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7583  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7584  parentnewbound = parentvar->glbdom.lb;
7585  }
7586  }
7587  else
7588  parentnewbound = -newbound;
7589  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7590  }
7591  break;
7592 
7593  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7594  assert(parentvar->negatedvar != NULL);
7595  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7596  assert(parentvar->negatedvar->negatedvar == parentvar);
7597  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7598  parentvar->data.negate.constant - newbound) );
7599  break;
7600 
7601  default:
7602  SCIPerrorMessage("unknown variable status\n");
7603  return SCIP_INVALIDDATA;
7604  }
7605  }
7606 
7607  return SCIP_OKAY;
7608 }
7609 
7610 /** performs the current change in upper bound, changes all parents accordingly */
7611 static
7613  SCIP_VAR* var, /**< problem variable to change */
7614  BMS_BLKMEM* blkmem, /**< block memory */
7615  SCIP_SET* set, /**< global SCIP settings */
7616  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7617  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7618  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7619  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7620  SCIP_Real newbound /**< new bound for variable */
7621  )
7622 {
7623  SCIP_VAR* parentvar;
7624  SCIP_Real oldbound;
7625  int i;
7626 
7627  assert(var != NULL);
7628  assert(set != NULL);
7629  assert(var->scip == set->scip);
7630  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7631  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7632  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7633  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7635 
7636  /* check that the bound is feasible */
7637  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7638  /* adjust bound to integral value if variable is of integral type */
7639  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7640 
7641  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7642  {
7643  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7644  newbound = MAX(newbound, var->locdom.lb);
7645 
7646  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7647  newbound = MIN(newbound, var->glbdom.ub);
7648  }
7649  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7650 
7651  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7652 
7653  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7654  newbound = var->glbdom.ub;
7655  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7656  return SCIP_OKAY;
7657 
7658  /* change the bound */
7659  oldbound = var->locdom.ub;
7660  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7661  var->locdom.ub = newbound;
7662 
7663  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7664  * once update the statistic
7665  */
7666  if( stat != NULL )
7667  SCIPstatIncrement(stat, set, domchgcount);
7668 
7669  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7670  {
7671  /* merges overlapping holes into single holes, moves bounds respectively */
7672  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7673  }
7674 
7675  /* issue bound change event */
7676  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7677  if( var->eventfilter != NULL )
7678  {
7679  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7680  }
7681 
7682  /* process parent variables */
7683  for( i = 0; i < var->nparentvars; ++i )
7684  {
7685  parentvar = var->parentvars[i];
7686  assert(parentvar != NULL);
7687 
7688  switch( SCIPvarGetStatus(parentvar) )
7689  {
7691  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7692  break;
7693 
7694  case SCIP_VARSTATUS_COLUMN:
7695  case SCIP_VARSTATUS_LOOSE:
7696  case SCIP_VARSTATUS_FIXED:
7698  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7699  return SCIP_INVALIDDATA;
7700 
7701  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7702  assert(parentvar->data.aggregate.var == var);
7703  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7704  {
7705  SCIP_Real parentnewbound;
7706 
7707  /* a > 0 -> change upper bound of x */
7708  assert(SCIPsetIsInfinity(set, parentvar->locdom.ub) || SCIPsetIsInfinity(set, oldbound)
7709  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7710  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7711  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7712  {
7713  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7714  /* 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
7715  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7716  * as a result, the parent's upper bound is set to it's lower bound, and not below
7717  */
7718  if( parentnewbound < parentvar->glbdom.lb )
7719  {
7720  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7721  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7722  parentnewbound = parentvar->glbdom.lb;
7723  }
7724  }
7725  else
7726  parentnewbound = newbound;
7727  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7728  }
7729  else
7730  {
7731  SCIP_Real parentnewbound;
7732 
7733  /* a < 0 -> change lower bound of x */
7734  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7735  assert(SCIPsetIsInfinity(set, -parentvar->locdom.lb) || SCIPsetIsInfinity(set, oldbound)
7736  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7737  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7738  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7739  {
7740  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7741  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7742  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7743  * as a result, the parent's lower bound is set to it's upper bound, and not above
7744  */
7745  if( parentnewbound > parentvar->glbdom.ub )
7746  {
7747  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7748  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7749  parentnewbound = parentvar->glbdom.ub;
7750  }
7751  }
7752  else
7753  parentnewbound = -newbound;
7754  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7755  }
7756  break;
7757 
7758  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7759  assert(parentvar->negatedvar != NULL);
7760  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7761  assert(parentvar->negatedvar->negatedvar == parentvar);
7762  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7763  parentvar->data.negate.constant - newbound) );
7764  break;
7765 
7766  default:
7767  SCIPerrorMessage("unknown variable status\n");
7768  return SCIP_INVALIDDATA;
7769  }
7770  }
7771 
7772  return SCIP_OKAY;
7773 }
7774 
7775 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7776  * information in variable
7777  */
7779  SCIP_VAR* var, /**< problem variable to change */
7780  BMS_BLKMEM* blkmem, /**< block memory */
7781  SCIP_SET* set, /**< global SCIP settings */
7782  SCIP_STAT* stat, /**< problem statistics */
7783  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7784  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7785  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7786  SCIP_Real newbound /**< new bound for variable */
7787  )
7788 {
7789  assert(var != NULL);
7790  assert(blkmem != NULL);
7791  assert(set != NULL);
7792  assert(var->scip == set->scip);
7793 
7794  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7795  * of the domain within feastol
7796  */
7797  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7798 
7799  /* adjust bound to integral value if variable is of integral type */
7800  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7801 
7802  /* check that the adjusted bound is feasible */
7803  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7804 
7805  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7806  {
7807  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7808  newbound = MIN(newbound, var->locdom.ub);
7809  }
7810  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7811 
7812  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7813 
7814  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) /*lint !e777*/
7815  && !(newbound != var->locdom.lb && newbound * var->locdom.lb <= 0.0) ) /*lint !e777*/
7816  return SCIP_OKAY;
7817 
7818  /* change bounds of attached variables */
7819  switch( SCIPvarGetStatus(var) )
7820  {
7822  if( var->data.original.transvar != NULL )
7823  {
7824  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7825  newbound) );
7826  }
7827  else
7828  {
7829  assert(set->stage == SCIP_STAGE_PROBLEM);
7830  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7831  }
7832  break;
7833 
7834  case SCIP_VARSTATUS_COLUMN:
7835  case SCIP_VARSTATUS_LOOSE:
7836  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7837  break;
7838 
7839  case SCIP_VARSTATUS_FIXED:
7840  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7841  return SCIP_INVALIDDATA;
7842 
7843  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7844  assert(var->data.aggregate.var != NULL);
7845  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7846  {
7847  SCIP_Real childnewbound;
7848 
7849  /* a > 0 -> change lower bound of y */
7850  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7851  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7853  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7854  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7855  else
7856  childnewbound = newbound;
7857  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7858  childnewbound) );
7859  }
7860  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7861  {
7862  SCIP_Real childnewbound;
7863 
7864  /* a < 0 -> change upper bound of y */
7865  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7866  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7868  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7869  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7870  else
7871  childnewbound = -newbound;
7872  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7873  childnewbound) );
7874  }
7875  else
7876  {
7877  SCIPerrorMessage("scalar is zero in aggregation\n");
7878  return SCIP_INVALIDDATA;
7879  }
7880  break;
7881 
7883  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7884  return SCIP_INVALIDDATA;
7885 
7886  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7887  assert(var->negatedvar != NULL);
7889  assert(var->negatedvar->negatedvar == var);
7890  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7891  var->data.negate.constant - newbound) );
7892  break;
7893 
7894  default:
7895  SCIPerrorMessage("unknown variable status\n");
7896  return SCIP_INVALIDDATA;
7897  }
7898 
7899  return SCIP_OKAY;
7900 }
7901 
7902 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7903  * information in variable
7904  */
7906  SCIP_VAR* var, /**< problem variable to change */
7907  BMS_BLKMEM* blkmem, /**< block memory */
7908  SCIP_SET* set, /**< global SCIP settings */
7909  SCIP_STAT* stat, /**< problem statistics */
7910  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7911  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7912  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7913  SCIP_Real newbound /**< new bound for variable */
7914  )
7915 {
7916  assert(var != NULL);
7917  assert(blkmem != NULL);
7918  assert(set != NULL);
7919  assert(var->scip == set->scip);
7920 
7921  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7922  * of the domain within feastol
7923  */
7924  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7925 
7926  /* adjust bound to integral value if variable is of integral type */
7927  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7928 
7929  /* check that the adjusted bound is feasible */
7930  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7931 
7932  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7933  {
7934  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7935  newbound = MAX(newbound, var->locdom.lb);
7936  }
7937  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7938 
7939  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7940 
7941  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) /*lint !e777*/
7942  && !(newbound != var->locdom.ub && newbound * var->locdom.ub <= 0.0) ) /*lint !e777*/
7943  return SCIP_OKAY;
7944 
7945  /* change bounds of attached variables */
7946  switch( SCIPvarGetStatus(var) )
7947  {
7949  if( var->data.original.transvar != NULL )
7950  {
7951  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7952  }
7953  else
7954  {
7955  assert(set->stage == SCIP_STAGE_PROBLEM);
7956  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7957  }
7958  break;
7959 
7960  case SCIP_VARSTATUS_COLUMN:
7961  case SCIP_VARSTATUS_LOOSE:
7962  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7963  break;
7964 
7965  case SCIP_VARSTATUS_FIXED:
7966  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7967  return SCIP_INVALIDDATA;
7968 
7969  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7970  assert(var->data.aggregate.var != NULL);
7971  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7972  {
7973  SCIP_Real childnewbound;
7974 
7975  /* a > 0 -> change upper bound of y */
7976  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7977  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7979  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7980  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7981  else
7982  childnewbound = newbound;
7983  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7984  childnewbound) );
7985  }
7986  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7987  {
7988  SCIP_Real childnewbound;
7989 
7990  /* a < 0 -> change lower bound of y */
7991  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7992  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7994  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7995  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7996  else
7997  childnewbound = -newbound;
7998  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7999  childnewbound) );
8000  }
8001  else
8002  {
8003  SCIPerrorMessage("scalar is zero in aggregation\n");
8004  return SCIP_INVALIDDATA;
8005  }
8006  break;
8007 
8009  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8010  return SCIP_INVALIDDATA;
8011 
8012  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8013  assert(var->negatedvar != NULL);
8015  assert(var->negatedvar->negatedvar == var);
8016  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
8017  var->data.negate.constant - newbound) );
8018  break;
8019 
8020  default:
8021  SCIPerrorMessage("unknown variable status\n");
8022  return SCIP_INVALIDDATA;
8023  }
8024 
8025  return SCIP_OKAY;
8026 }
8027 
8028 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
8029  * information in variable
8030  */
8032  SCIP_VAR* var, /**< problem variable to change */
8033  BMS_BLKMEM* blkmem, /**< block memory */
8034  SCIP_SET* set, /**< global SCIP settings */
8035  SCIP_STAT* stat, /**< problem statistics */
8036  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
8037  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
8038  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8039  SCIP_Real newbound, /**< new bound for variable */
8040  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
8041  )
8042 {
8043  /* apply bound change to the LP data */
8044  switch( boundtype )
8045  {
8046  case SCIP_BOUNDTYPE_LOWER:
8047  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8048  case SCIP_BOUNDTYPE_UPPER:
8049  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
8050  default:
8051  SCIPerrorMessage("unknown bound type\n");
8052  return SCIP_INVALIDDATA;
8053  }
8054 }
8055 
8056 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
8058  SCIP_VAR* var, /**< problem variable to change */
8059  SCIP_SET* set, /**< global SCIP settings */
8060  SCIP_LP* lp, /**< current LP data */
8061  SCIP_Real newbound /**< new bound for variable */
8062  )
8063 {
8064  assert(var != NULL);
8065  assert(set != NULL);
8066  assert(var->scip == set->scip);
8067  assert(lp != NULL);
8068  assert(SCIPlpDiving(lp));
8069 
8070  /* adjust bound for integral variables */
8071  SCIPvarAdjustLb(var, set, &newbound);
8072 
8073  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
8074 
8075  /* change bounds of attached variables */
8076  switch( SCIPvarGetStatus(var) )
8077  {
8079  assert(var->data.original.transvar != NULL);
8080  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
8081  break;
8082 
8083  case SCIP_VARSTATUS_COLUMN:
8084  assert(var->data.col != NULL);
8085  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
8086  break;
8087 
8088  case SCIP_VARSTATUS_LOOSE:
8089  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8090  return SCIP_INVALIDDATA;
8091 
8092  case SCIP_VARSTATUS_FIXED:
8093  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8094  return SCIP_INVALIDDATA;
8095 
8096  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8097  assert(var->data.aggregate.var != NULL);
8098  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8099  {
8100  SCIP_Real childnewbound;
8101 
8102  /* a > 0 -> change lower bound of y */
8103  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8104  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8105  else
8106  childnewbound = newbound;
8107  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8108  }
8109  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8110  {
8111  SCIP_Real childnewbound;
8112 
8113  /* a < 0 -> change upper bound of y */
8114  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8115  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8116  else
8117  childnewbound = -newbound;
8118  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8119  }
8120  else
8121  {
8122  SCIPerrorMessage("scalar is zero in aggregation\n");
8123  return SCIP_INVALIDDATA;
8124  }
8125  break;
8126 
8128  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8129  return SCIP_INVALIDDATA;
8130 
8131  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8132  assert(var->negatedvar != NULL);
8134  assert(var->negatedvar->negatedvar == var);
8135  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8136  break;
8137 
8138  default:
8139  SCIPerrorMessage("unknown variable status\n");
8140  return SCIP_INVALIDDATA;
8141  }
8142 
8143  return SCIP_OKAY;
8144 }
8145 
8146 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
8148  SCIP_VAR* var, /**< problem variable to change */
8149  SCIP_SET* set, /**< global SCIP settings */
8150  SCIP_LP* lp, /**< current LP data */
8151  SCIP_Real newbound /**< new bound for variable */
8152  )
8153 {
8154  assert(var != NULL);
8155  assert(set != NULL);
8156  assert(var->scip == set->scip);
8157  assert(lp != NULL);
8158  assert(SCIPlpDiving(lp));
8159 
8160  /* adjust bound for integral variables */
8161  SCIPvarAdjustUb(var, set, &newbound);
8162 
8163  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
8164 
8165  /* change bounds of attached variables */
8166  switch( SCIPvarGetStatus(var) )
8167  {
8169  assert(var->data.original.transvar != NULL);
8170  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
8171  break;
8172 
8173  case SCIP_VARSTATUS_COLUMN:
8174  assert(var->data.col != NULL);
8175  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8176  break;
8177 
8178  case SCIP_VARSTATUS_LOOSE:
8179  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8180  return SCIP_INVALIDDATA;
8181 
8182  case SCIP_VARSTATUS_FIXED:
8183  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8184  return SCIP_INVALIDDATA;
8185 
8186  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8187  assert(var->data.aggregate.var != NULL);
8188  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8189  {
8190  SCIP_Real childnewbound;
8191 
8192  /* a > 0 -> change upper bound of y */
8193  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8194  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8195  else
8196  childnewbound = newbound;
8197  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8198  }
8199  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8200  {
8201  SCIP_Real childnewbound;
8202 
8203  /* a < 0 -> change lower bound of y */
8204  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8205  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8206  else
8207  childnewbound = -newbound;
8208  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8209  }
8210  else
8211  {
8212  SCIPerrorMessage("scalar is zero in aggregation\n");
8213  return SCIP_INVALIDDATA;
8214  }
8215  break;
8216 
8218  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8219  return SCIP_INVALIDDATA;
8220 
8221  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8222  assert(var->negatedvar != NULL);
8224  assert(var->negatedvar->negatedvar == var);
8225  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8226  break;
8227 
8228  default:
8229  SCIPerrorMessage("unknown variable status\n");
8230  return SCIP_INVALIDDATA;
8231  }
8232 
8233  return SCIP_OKAY;
8234 }
8235 
8236 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8237  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8238  * not updated if bounds of aggregation variables are changing
8239  *
8240  * calling this function for a non-multi-aggregated variable is not allowed
8241  */
8243  SCIP_VAR* var, /**< problem variable */
8244  SCIP_SET* set /**< global SCIP settings */
8245  )
8246 {
8247  int i;
8248  SCIP_Real lb;
8249  SCIP_Real bnd;
8250  SCIP_VAR* aggrvar;
8251  SCIP_Bool posinf;
8252  SCIP_Bool neginf;
8253 
8254  assert(var != NULL);
8255  assert(set != NULL);
8256  assert(var->scip == set->scip);
8258 
8259  posinf = FALSE;
8260  neginf = FALSE;
8261  lb = var->data.multaggr.constant;
8262  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8263  {
8264  aggrvar = var->data.multaggr.vars[i];
8265  if( var->data.multaggr.scalars[i] > 0.0 )
8266  {
8267  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8268 
8269  if( SCIPsetIsInfinity(set, bnd) )
8270  posinf = TRUE;
8271  else if( SCIPsetIsInfinity(set, -bnd) )
8272  neginf = TRUE;
8273  else
8274  lb += var->data.multaggr.scalars[i] * bnd;
8275  }
8276  else
8277  {
8278  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8279 
8280  if( SCIPsetIsInfinity(set, -bnd) )
8281  posinf = TRUE;
8282  else if( SCIPsetIsInfinity(set, bnd) )
8283  neginf = TRUE;
8284  else
8285  lb += var->data.multaggr.scalars[i] * bnd;
8286  }
8287 
8288  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8289  * variable
8290  */
8291  if( neginf )
8292  return SCIPvarGetLbLocal(var);
8293  }
8294 
8295  /* if positive infinity flag was set to true return infinity */
8296  if( posinf )
8297  return SCIPsetInfinity(set);
8298 
8299  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8300 }
8301 
8302 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8303  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8304  * not updated if bounds of aggregation variables are changing
8305  *
8306  * calling this function for a non-multi-aggregated variable is not allowed
8307  */
8309  SCIP_VAR* var, /**< problem variable */
8310  SCIP_SET* set /**< global SCIP settings */
8311  )
8312 {
8313  int i;
8314  SCIP_Real ub;
8315  SCIP_Real bnd;
8316  SCIP_VAR* aggrvar;
8317  SCIP_Bool posinf;
8318  SCIP_Bool neginf;
8319 
8320  assert(var != NULL);
8321  assert(set != NULL);
8322  assert(var->scip == set->scip);
8324 
8325  posinf = FALSE;
8326  neginf = FALSE;
8327  ub = var->data.multaggr.constant;
8328  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8329  {
8330  aggrvar = var->data.multaggr.vars[i];
8331  if( var->data.multaggr.scalars[i] > 0.0 )
8332  {
8333  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8334 
8335  if( SCIPsetIsInfinity(set, bnd) )
8336  posinf = TRUE;
8337  else if( SCIPsetIsInfinity(set, -bnd) )
8338  neginf = TRUE;
8339  else
8340  ub += var->data.multaggr.scalars[i] * bnd;
8341  }
8342  else
8343  {
8344  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8345 
8346  if( SCIPsetIsInfinity(set, -bnd) )
8347  posinf = TRUE;
8348  else if( SCIPsetIsInfinity(set, bnd) )
8349  neginf = TRUE;
8350  else
8351  ub += var->data.multaggr.scalars[i] * bnd;
8352  }
8353 
8354  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8355  * variable
8356  */
8357  if( posinf )
8358  return SCIPvarGetUbLocal(var);
8359  }
8360 
8361  /* if negative infinity flag was set to true return -infinity */
8362  if( neginf )
8363  return -SCIPsetInfinity(set);
8364 
8365  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8366 }
8367 
8368 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8369  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8370  * not updated if bounds of aggregation variables are changing
8371  *
8372  * calling this function for a non-multi-aggregated variable is not allowed
8373  */
8375  SCIP_VAR* var, /**< problem variable */
8376  SCIP_SET* set /**< global SCIP settings */
8377  )
8378 {
8379  int i;
8380  SCIP_Real lb;
8381  SCIP_Real bnd;
8382  SCIP_VAR* aggrvar;
8383  SCIP_Bool posinf;
8384  SCIP_Bool neginf;
8385 
8386  assert(var != NULL);
8387  assert(set != NULL);
8388  assert(var->scip == set->scip);
8390 
8391  posinf = FALSE;
8392  neginf = FALSE;
8393  lb = var->data.multaggr.constant;
8394  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8395  {
8396  aggrvar = var->data.multaggr.vars[i];
8397  if( var->data.multaggr.scalars[i] > 0.0 )
8398  {
8399  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8400 
8401  if( SCIPsetIsInfinity(set, bnd) )
8402  posinf = TRUE;
8403  else if( SCIPsetIsInfinity(set, -bnd) )
8404  neginf = TRUE;
8405  else
8406  lb += var->data.multaggr.scalars[i] * bnd;
8407  }
8408  else
8409  {
8410  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8411 
8412  if( SCIPsetIsInfinity(set, -bnd) )
8413  posinf = TRUE;
8414  else if( SCIPsetIsInfinity(set, bnd) )
8415  neginf = TRUE;
8416  else
8417  lb += var->data.multaggr.scalars[i] * bnd;
8418  }
8419 
8420  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8421  * variable
8422  */
8423  if( neginf )
8424  return SCIPvarGetLbGlobal(var);
8425  }
8426 
8427  /* if positive infinity flag was set to true return infinity */
8428  if( posinf )
8429  return SCIPsetInfinity(set);
8430 
8431  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8432 }
8433 
8434 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8435  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8436  * not updated if bounds of aggregation variables are changing
8437  *
8438  * calling this function for a non-multi-aggregated variable is not allowed
8439  */
8441  SCIP_VAR* var, /**< problem variable */
8442  SCIP_SET* set /**< global SCIP settings */
8443  )
8444 {
8445  int i;
8446  SCIP_Real ub;
8447  SCIP_Real bnd;
8448  SCIP_VAR* aggrvar;
8449  SCIP_Bool posinf;
8450  SCIP_Bool neginf;
8451 
8452  assert(var != NULL);
8453  assert(set != NULL);
8454  assert(var->scip == set->scip);
8456 
8457  posinf = FALSE;
8458  neginf = FALSE;
8459  ub = var->data.multaggr.constant;
8460  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8461  {
8462  aggrvar = var->data.multaggr.vars[i];
8463  if( var->data.multaggr.scalars[i] > 0.0 )
8464  {
8465  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8466 
8467  if( SCIPsetIsInfinity(set, bnd) )
8468  posinf = TRUE;
8469  else if( SCIPsetIsInfinity(set, -bnd) )
8470  neginf = TRUE;
8471  else
8472  ub += var->data.multaggr.scalars[i] * bnd;
8473  }
8474  else
8475  {
8476  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8477 
8478  if( SCIPsetIsInfinity(set, -bnd) )
8479  posinf = TRUE;
8480  else if( SCIPsetIsInfinity(set, bnd) )
8481  neginf = TRUE;
8482  else
8483  ub += var->data.multaggr.scalars[i] * bnd;
8484  }
8485 
8486  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8487  * variable
8488  */
8489  if( posinf )
8490  return SCIPvarGetUbGlobal(var);
8491  }
8492 
8493  /* if negative infinity flag was set to true return -infinity */
8494  if( neginf )
8495  return -SCIPsetInfinity(set);
8496 
8497  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8498 }
8499 
8500 /** adds a hole to the original domain of the variable */
8502  SCIP_VAR* var, /**< problem variable */
8503  BMS_BLKMEM* blkmem, /**< block memory */
8504  SCIP_SET* set, /**< global SCIP settings */
8505  SCIP_Real left, /**< left bound of open interval in new hole */
8506  SCIP_Real right /**< right bound of open interval in new hole */
8507  )
8508 {
8509  SCIP_Bool added;
8510 
8511  assert(var != NULL);
8512  assert(!SCIPvarIsTransformed(var));
8514  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8515  assert(set != NULL);
8516  assert(var->scip == set->scip);
8517  assert(set->stage == SCIP_STAGE_PROBLEM);
8518 
8519  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8520 
8521  if( SCIPsetIsEQ(set, left, right) )
8522  return SCIP_OKAY;
8523 
8524  /* the interval should not be empty */
8525  assert(SCIPsetIsLT(set, left, right));
8526 
8527  /* the the interval bound should already be adjusted */
8528  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8529  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8530 
8531  /* the the interval should lay between the lower and upper bound */
8532  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8533  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8534 
8535  /* add domain hole */
8536  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8537 
8538  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8539  if( added )
8540  {
8541  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8542  }
8543 
8544  /**@todo add hole in parent and child variables (just like with bound changes);
8545  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8546  */
8547 
8548  return SCIP_OKAY;
8549 }
8550 
8551 /** performs the current add of domain, changes all parents accordingly */
8552 static
8554  SCIP_VAR* var, /**< problem variable */
8555  BMS_BLKMEM* blkmem, /**< block memory */
8556  SCIP_SET* set, /**< global SCIP settings */
8557  SCIP_STAT* stat, /**< problem statistics */
8558  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8559  SCIP_Real left, /**< left bound of open interval in new hole */
8560  SCIP_Real right, /**< right bound of open interval in new hole */
8561  SCIP_Bool* added /**< pointer to store whether the hole was added */
8562  )
8563 {
8564  SCIP_VAR* parentvar;
8565  SCIP_Real newlb;
8566  SCIP_Real newub;
8567  int i;
8568 
8569  assert(var != NULL);
8570  assert(added != NULL);
8571  assert(blkmem != NULL);
8572 
8573  /* the interval should not be empty */
8574  assert(SCIPsetIsLT(set, left, right));
8575 
8576  /* the interval bound should already be adjusted */
8577  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8578  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8579 
8580  /* the interval should lay between the lower and upper bound */
8581  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8582  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8583 
8584  /* @todo add debugging mechanism for holes when using a debugging solution */
8585 
8586  /* add hole to hole list */
8587  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8588 
8589  /* check if the hole is redundant */
8590  if( !(*added) )
8591  return SCIP_OKAY;
8592 
8593  /* current bounds */
8594  newlb = var->glbdom.lb;
8595  newub = var->glbdom.ub;
8596 
8597  /* merge domain holes */
8598  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8599 
8600  /* the bound should not be changed */
8601  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8602  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8603 
8604  /* issue bound change event */
8605  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8606  if( var->eventfilter != NULL )
8607  {
8608  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8609  }
8610 
8611  /* process parent variables */
8612  for( i = 0; i < var->nparentvars; ++i )
8613  {
8614  SCIP_Real parentnewleft;
8615  SCIP_Real parentnewright;
8616  SCIP_Bool localadded;
8617 
8618  parentvar = var->parentvars[i];
8619  assert(parentvar != NULL);
8620 
8621  switch( SCIPvarGetStatus(parentvar) )
8622  {
8624  parentnewleft = left;
8625  parentnewright = right;
8626  break;
8627 
8628  case SCIP_VARSTATUS_COLUMN:
8629  case SCIP_VARSTATUS_LOOSE:
8630  case SCIP_VARSTATUS_FIXED:
8632  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8633  return SCIP_INVALIDDATA;
8634 
8635  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8636  assert(parentvar->data.aggregate.var == var);
8637 
8638  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8639  {
8640  /* a > 0 -> change upper bound of x */
8641  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8642  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8643  }
8644  else
8645  {
8646  /* a < 0 -> change lower bound of x */
8647  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8648 
8649  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8650  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8651  }
8652  break;
8653 
8654  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8655  assert(parentvar->negatedvar != NULL);
8656  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8657  assert(parentvar->negatedvar->negatedvar == parentvar);
8658 
8659  parentnewright = -left + parentvar->data.negate.constant;
8660  parentnewleft = -right + parentvar->data.negate.constant;
8661  break;
8662 
8663  default:
8664  SCIPerrorMessage("unknown variable status\n");
8665  return SCIP_INVALIDDATA;
8666  }
8667 
8668  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8669 
8670  /* perform hole added for parent variable */
8671  assert(blkmem != NULL);
8672  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8673  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8674  parentnewleft, parentnewright, &localadded) );
8675  assert(localadded);
8676  }
8677 
8678  return SCIP_OKAY;
8679 }
8680 
8681 /** adds a hole to the variable's global and local domain */
8683  SCIP_VAR* var, /**< problem variable */
8684  BMS_BLKMEM* blkmem, /**< block memory */
8685  SCIP_SET* set, /**< global SCIP settings */
8686  SCIP_STAT* stat, /**< problem statistics */
8687  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8688  SCIP_Real left, /**< left bound of open interval in new hole */
8689  SCIP_Real right, /**< right bound of open interval in new hole */
8690  SCIP_Bool* added /**< pointer to store whether the hole was added */
8691  )
8692 {
8693  SCIP_Real childnewleft;
8694  SCIP_Real childnewright;
8695 
8696  assert(var != NULL);
8697  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8698  assert(blkmem != NULL);
8699  assert(added != NULL);
8700 
8701  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8702 
8703  /* the interval should not be empty */
8704  assert(SCIPsetIsLT(set, left, right));
8705 
8706  /* the the interval bound should already be adjusted */
8707  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8708  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8709 
8710  /* the the interval should lay between the lower and upper bound */
8711  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8712  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8713 
8714  /* change bounds of attached variables */
8715  switch( SCIPvarGetStatus(var) )
8716  {
8718  if( var->data.original.transvar != NULL )
8719  {
8720  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8721  left, right, added) );
8722  }
8723  else
8724  {
8725  assert(set->stage == SCIP_STAGE_PROBLEM);
8726 
8727  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8728  if( *added )
8729  {
8730  SCIP_Bool localadded;
8731 
8732  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8733  }
8734  }
8735  break;
8736 
8737  case SCIP_VARSTATUS_COLUMN:
8738  case SCIP_VARSTATUS_LOOSE:
8739  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8740  if( *added )
8741  {
8742  SCIP_Bool localadded;
8743 
8744  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8745  }
8746  break;
8747 
8748  case SCIP_VARSTATUS_FIXED:
8749  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8750  return SCIP_INVALIDDATA;
8751 
8752  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8753  assert(var->data.aggregate.var != NULL);
8754 
8755  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8756  {
8757  /* a > 0 -> change lower bound of y */
8758  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8759  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8760  }
8761  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8762  {
8763  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8764  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8765  }
8766  else
8767  {
8768  SCIPerrorMessage("scalar is zero in aggregation\n");
8769  return SCIP_INVALIDDATA;
8770  }
8771  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8772  childnewleft, childnewright, added) );
8773  break;
8774 
8776  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8777  return SCIP_INVALIDDATA;
8778 
8779  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8780  assert(var->negatedvar != NULL);
8782  assert(var->negatedvar->negatedvar == var);
8783 
8784  childnewright = -left + var->data.negate.constant;
8785  childnewleft = -right + var->data.negate.constant;
8786 
8787  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8788  childnewleft, childnewright, added) );
8789  break;
8790 
8791  default:
8792  SCIPerrorMessage("unknown variable status\n");
8793  return SCIP_INVALIDDATA;
8794  }
8795 
8796  return SCIP_OKAY;
8797 }
8798 
8799 /** performs the current add of domain, changes all parents accordingly */
8800 static
8802  SCIP_VAR* var, /**< problem variable */
8803  BMS_BLKMEM* blkmem, /**< block memory */
8804  SCIP_SET* set, /**< global SCIP settings */
8805  SCIP_STAT* stat, /**< problem statistics */
8806  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8807  SCIP_Real left, /**< left bound of open interval in new hole */
8808  SCIP_Real right, /**< right bound of open interval in new hole */
8809  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8810  )
8811 {
8812  SCIP_VAR* parentvar;
8813  SCIP_Real newlb;
8814  SCIP_Real newub;
8815  int i;
8816 
8817  assert(var != NULL);
8818  assert(added != NULL);
8819  assert(blkmem != NULL);
8820 
8821  /* the interval should not be empty */
8822  assert(SCIPsetIsLT(set, left, right));
8823 
8824  /* the the interval bound should already be adjusted */
8825  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8826  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8827 
8828  /* the the interval should lay between the lower and upper bound */
8829  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8830  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8831 
8832  /* add hole to hole list */
8833  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8834 
8835  /* check if the hole is redundant */
8836  if( !(*added) )
8837  return SCIP_OKAY;
8838 
8839  /* current bounds */
8840  newlb = var->locdom.lb;
8841  newub = var->locdom.ub;
8842 
8843  /* merge domain holes */
8844  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8845 
8846  /* the bound should not be changed */
8847  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8848  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8849 
8850 #if 0
8851  /* issue bound change event */
8852  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8853  if( var->eventfilter != NULL )
8854  {
8855  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8856  }
8857 #endif
8858 
8859  /* process parent variables */
8860  for( i = 0; i < var->nparentvars; ++i )
8861  {
8862  SCIP_Real parentnewleft;
8863  SCIP_Real parentnewright;
8864  SCIP_Bool localadded;
8865 
8866  parentvar = var->parentvars[i];
8867  assert(parentvar != NULL);
8868 
8869  switch( SCIPvarGetStatus(parentvar) )
8870  {
8872  parentnewleft = left;
8873  parentnewright = right;
8874  break;
8875 
8876  case SCIP_VARSTATUS_COLUMN:
8877  case SCIP_VARSTATUS_LOOSE:
8878  case SCIP_VARSTATUS_FIXED:
8880  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8881  return SCIP_INVALIDDATA;
8882 
8883  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8884  assert(parentvar->data.aggregate.var == var);
8885 
8886  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8887  {
8888  /* a > 0 -> change upper bound of x */
8889  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8890  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8891  }
8892  else
8893  {
8894  /* a < 0 -> change lower bound of x */
8895  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8896 
8897  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8898  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8899  }
8900  break;
8901 
8902  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8903  assert(parentvar->negatedvar != NULL);
8904  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8905  assert(parentvar->negatedvar->negatedvar == parentvar);
8906 
8907  parentnewright = -left + parentvar->data.negate.constant;
8908  parentnewleft = -right + parentvar->data.negate.constant;
8909  break;
8910 
8911  default:
8912  SCIPerrorMessage("unknown variable status\n");
8913  return SCIP_INVALIDDATA;
8914  }
8915 
8916  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8917 
8918  /* perform hole added for parent variable */
8919  assert(blkmem != NULL);
8920  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8921  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8922  parentnewleft, parentnewright, &localadded) );
8923  assert(localadded);
8924  }
8925 
8926  return SCIP_OKAY;
8927 }
8928 
8929 /** adds a hole to the variable's current local domain */
8931  SCIP_VAR* var, /**< problem variable */
8932  BMS_BLKMEM* blkmem, /**< block memory */
8933  SCIP_SET* set, /**< global SCIP settings */
8934  SCIP_STAT* stat, /**< problem statistics */
8935  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8936  SCIP_Real left, /**< left bound of open interval in new hole */
8937  SCIP_Real right, /**< right bound of open interval in new hole */
8938  SCIP_Bool* added /**< pointer to store whether the hole was added */
8939  )
8940 {
8941  SCIP_Real childnewleft;
8942  SCIP_Real childnewright;
8943 
8944  assert(var != NULL);
8945 
8946  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8947 
8948  assert(set != NULL);
8949  assert(var->scip == set->scip);
8950  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8951  assert(blkmem != NULL);
8952  assert(added != NULL);
8953 
8954  /* the interval should not be empty */
8955  assert(SCIPsetIsLT(set, left, right));
8956 
8957  /* the the interval bound should already be adjusted */
8958  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8959  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8960 
8961  /* the the interval should lay between the lower and upper bound */
8962  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8963  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8964 
8965  /* change bounds of attached variables */
8966  switch( SCIPvarGetStatus(var) )
8967  {
8969  if( var->data.original.transvar != NULL )
8970  {
8971  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8972  left, right, added) );
8973  }
8974  else
8975  {
8976  assert(set->stage == SCIP_STAGE_PROBLEM);
8977  SCIPstatIncrement(stat, set, domchgcount);
8978  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8979  }
8980  break;
8981 
8982  case SCIP_VARSTATUS_COLUMN:
8983  case SCIP_VARSTATUS_LOOSE:
8984  SCIPstatIncrement(stat, set, domchgcount);
8985  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8986  break;
8987 
8988  case SCIP_VARSTATUS_FIXED:
8989  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8990  return SCIP_INVALIDDATA;
8991 
8992  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8993  assert(var->data.aggregate.var != NULL);
8994 
8995  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8996  {
8997  /* a > 0 -> change lower bound of y */
8998  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8999  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9000  }
9001  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9002  {
9003  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
9004  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
9005  }
9006  else
9007  {
9008  SCIPerrorMessage("scalar is zero in aggregation\n");
9009  return SCIP_INVALIDDATA;
9010  }
9011  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
9012  childnewleft, childnewright, added) );
9013  break;
9014 
9016  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
9017  return SCIP_INVALIDDATA;
9018 
9019  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
9020  assert(var->negatedvar != NULL);
9022  assert(var->negatedvar->negatedvar == var);
9023 
9024  childnewright = -left + var->data.negate.constant;
9025  childnewleft = -right + var->data.negate.constant;
9026 
9027  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
9028  break;
9029 
9030  default:
9031  SCIPerrorMessage("unknown variable status\n");
9032  return SCIP_INVALIDDATA;
9033  }
9034 
9035  return SCIP_OKAY;
9036 }
9037 
9038 /** resets the global and local bounds of original variable to their original values */
9040  SCIP_VAR* var, /**< problem variable */
9041  BMS_BLKMEM* blkmem, /**< block memory */
9042  SCIP_SET* set, /**< global SCIP settings */
9043  SCIP_STAT* stat /**< problem statistics */
9044  )
9045 {
9046  assert(var != NULL);
9047  assert(set != NULL);
9048  assert(var->scip == set->scip);
9049  assert(SCIPvarIsOriginal(var));
9050  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
9051  * the transformed variable has been fixed */
9052  assert(SCIPvarGetTransVar(var) == NULL);
9053 
9054  /* copy the original bounds back to the global and local bounds */
9055  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
9056  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
9057  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
9058  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
9059 
9060  /* free the global and local holelists and duplicate the original ones */
9061  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
9062  holelistFree(&var->glbdom.holelist, blkmem);
9063  holelistFree(&var->locdom.holelist, blkmem);
9064  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9065  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
9066 
9067  return SCIP_OKAY;
9068 }
9069 
9070 /** issues a IMPLADDED event on the given variable */
9071 static
9073  SCIP_VAR* var, /**< problem variable to change */
9074  BMS_BLKMEM* blkmem, /**< block memory */
9075  SCIP_SET* set, /**< global SCIP settings */
9076  SCIP_EVENTQUEUE* eventqueue /**< event queue */
9077  )
9078 {
9079  SCIP_EVENT* event;
9080 
9081  assert(var != NULL);
9082 
9083  /* issue IMPLADDED event on variable */
9084  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
9085  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
9086 
9087  return SCIP_OKAY;
9088 }
9089 
9090 /** actually performs the addition of a variable bound to the variable's vbound arrays */
9091 static
9093  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
9094  BMS_BLKMEM* blkmem, /**< block memory */
9095  SCIP_SET* set, /**< global SCIP settings */
9096  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9097  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
9098  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
9099  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
9100  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
9101  )
9102 {
9103  SCIP_Bool added;
9104 
9105  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
9106  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
9107  * variable of the aggregated variable might be the same as the one its gets aggregated too.
9108  *
9109  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
9110  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
9111  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
9112  * variable bound can be ignored.
9113  *
9114  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
9115  * equivalence of the variables should be checked here.
9116  */
9117  if( var == vbvar )
9118  {
9119  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
9120  * can be checked via the global bounds of the variable */
9121 #ifndef NDEBUG
9122  SCIP_Real lb;
9123  SCIP_Real ub;
9124 
9125  lb = SCIPvarGetLbGlobal(var);
9126  ub = SCIPvarGetUbGlobal(var);
9127 
9128  if(vbtype == SCIP_BOUNDTYPE_LOWER)
9129  {
9130  if( vbcoef > 0.0 )
9131  {
9132  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
9133  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
9134  }
9135  else
9136  {
9137  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
9138  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
9139  }
9140  }
9141  else
9142  {
9143  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
9144  if( vbcoef > 0.0 )
9145  {
9146  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
9147  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
9148  }
9149  else
9150  {
9151  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
9152  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
9153  }
9154  }
9155 #endif
9156  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
9157  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9158 
9159  return SCIP_OKAY;
9160  }
9161 
9162  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
9163  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
9164 
9165  /* check variable bound on debugging solution */
9166  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
9167 
9168  /* perform the addition */
9169  if( vbtype == SCIP_BOUNDTYPE_LOWER )
9170  {
9171  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9172  }
9173  else
9174  {
9175  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9176  }
9177  var->closestvblpcount = -1;
9178 
9179  if( added )
9180  {
9181  /* issue IMPLADDED event */
9182  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9183  }
9184 
9185  return SCIP_OKAY;
9186 }
9187 
9188 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9189 static
9190 void checkImplic(
9191  SCIP_SET* set, /**< global SCIP settings */
9192  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9193  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9194  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9195  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9196  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9197  )
9198 {
9199  SCIP_Real impllb;
9200  SCIP_Real implub;
9201 
9202  assert(redundant != NULL);
9203  assert(infeasible != NULL);
9204 
9205  impllb = SCIPvarGetLbGlobal(implvar);
9206  implub = SCIPvarGetUbGlobal(implvar);
9207  if( impltype == SCIP_BOUNDTYPE_LOWER )
9208  {
9209  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9210  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9211  }
9212  else
9213  {
9214  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9215  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9216  }
9217 }
9218 
9219 /** applies the given implication, if it is not redundant */
9220 static
9222  BMS_BLKMEM* blkmem, /**< block memory */
9223  SCIP_SET* set, /**< global SCIP settings */
9224  SCIP_STAT* stat, /**< problem statistics */
9225  SCIP_PROB* transprob, /**< transformed problem */
9226  SCIP_PROB* origprob, /**< original problem */
9227  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9228  SCIP_REOPT* reopt, /**< reoptimization data structure */
9229  SCIP_LP* lp, /**< current LP data */
9230  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9231  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9232  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9233  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9234  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9235  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9236  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9237  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9238  )
9239 {
9240  SCIP_Real implub;
9241  SCIP_Real impllb;
9242 
9243  assert(infeasible != NULL);
9244 
9245  *infeasible = FALSE;
9246 
9247  implub = SCIPvarGetUbGlobal(implvar);
9248  impllb = SCIPvarGetLbGlobal(implvar);
9249  if( impltype == SCIP_BOUNDTYPE_LOWER )
9250  {
9251  if( SCIPsetIsFeasGT(set, implbound, implub) )
9252  {
9253  /* the implication produces a conflict: the problem is infeasible */
9254  *infeasible = TRUE;
9255  }
9256  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9257  {
9258  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9259  * with the local bound, in this case we need to store the bound change as pending bound change
9260  */
9261  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9262  {
9263  assert(tree != NULL);
9264  assert(transprob != NULL);
9265  assert(SCIPprobIsTransformed(transprob));
9266 
9267  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9268  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9269  }
9270  else
9271  {
9272  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9273  }
9274 
9275  if( nbdchgs != NULL )
9276  (*nbdchgs)++;
9277  }
9278  }
9279  else
9280  {
9281  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9282  {
9283  /* the implication produces a conflict: the problem is infeasible */
9284  *infeasible = TRUE;
9285  }
9286  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9287  {
9288  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9289  * with the local bound, in this case we need to store the bound change as pending bound change
9290  */
9291  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9292  {
9293  assert(tree != NULL);
9294  assert(transprob != NULL);
9295  assert(SCIPprobIsTransformed(transprob));
9296 
9297  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9298  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9299  }
9300  else
9301  {
9302  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9303  }
9304 
9305  if( nbdchgs != NULL )
9306  (*nbdchgs)++;
9307  }
9308  }
9309 
9310  return SCIP_OKAY;
9311 }
9312 
9313 /** actually performs the addition of an implication to the variable's implication arrays,
9314  * and adds the corresponding implication or variable bound to the implied variable;
9315  * if the implication is conflicting, the variable is fixed to the opposite value;
9316  * if the variable is already fixed to the given value, the implication is performed immediately;
9317  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9318  */
9319 static
9321  SCIP_VAR* var, /**< problem variable */
9322  BMS_BLKMEM* blkmem, /**< block memory */
9323  SCIP_SET* set, /**< global SCIP settings */
9324  SCIP_STAT* stat, /**< problem statistics */
9325  SCIP_PROB* transprob, /**< transformed problem */
9326  SCIP_PROB* origprob, /**< original problem */
9327  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9328  SCIP_REOPT* reopt, /**< reoptimization data structure */
9329  SCIP_LP* lp, /**< current LP data */
9330  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9331  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9332  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9333  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9334  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9335  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9336  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9337  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9338  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9339  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9340  SCIP_Bool* added /**< pointer to store whether an implication was added */
9341  )
9342 {
9343  SCIP_Bool redundant;
9344  SCIP_Bool conflict;
9345 
9346  assert(var != NULL);
9347  assert(SCIPvarIsActive(var));
9349  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9350  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9351  assert(infeasible != NULL);
9352  assert(added != NULL);
9353 
9354  /* check implication on debugging solution */
9355  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9356 
9357  *infeasible = FALSE;
9358  *added = FALSE;
9359 
9360  /* check, if the implication is redundant or infeasible */
9361  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9362  assert(!redundant || !conflict);
9363  if( redundant )
9364  return SCIP_OKAY;
9365 
9366  if( var == implvar )
9367  {
9368  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9369  * x == varfixing => x < 0 or x > 1
9370  */
9371  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9372  conflict = TRUE;
9373  else
9374  {
9375  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9376  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9377  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9378  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9379  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9380  if( !conflict )
9381  return SCIP_OKAY;
9382  }
9383  }
9384 
9385  /* check, if the variable is already fixed */
9386  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9387  {
9388  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9389  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9390  {
9391  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9392  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9393  }
9394  return SCIP_OKAY;
9395  }
9396 
9397  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9398  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9399 
9400  if( !conflict )
9401  {
9402  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9403 
9404  if( SCIPvarIsBinary(implvar) )
9405  {
9406  SCIP_VAR* vars[2];
9407  SCIP_Bool vals[2];
9408 
9409  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9410  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9411 
9412  vars[0] = var;
9413  vars[1] = implvar;
9414  vals[0] = varfixing;
9415  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9416 
9417  /* add the clique to the clique table */
9418  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9419  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9420 
9421  if( !conflict )
9422  return SCIP_OKAY;
9423  }
9424  else
9425  {
9426  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9427  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9428  SCIPvarGetName(var), varfixing,
9429  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9430  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9431  isshortcut, &conflict, added) );
9432  }
9433  }
9434  assert(!conflict || !(*added));
9435 
9436  /* on conflict, fix the variable to the opposite value */
9437  if( conflict )
9438  {
9439  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9440 
9441  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9442  * with the local bound, in this case we need to store the bound change as pending bound change
9443  */
9444  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9445  {
9446  assert(tree != NULL);
9447  assert(transprob != NULL);
9448  assert(SCIPprobIsTransformed(transprob));
9449 
9450  if( varfixing )
9451  {
9452  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9453  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9454  }
9455  else
9456  {
9457  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9458  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9459  }
9460  }
9461  else
9462  {
9463  if( varfixing )
9464  {
9465  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9466  }
9467  else
9468  {
9469  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9470  }
9471  }
9472  if( nbdchgs != NULL )
9473  (*nbdchgs)++;
9474 
9475  return SCIP_OKAY;
9476  }
9477  else if( *added )
9478  {
9479  /* issue IMPLADDED event */
9480  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9481  }
9482  else
9483  {
9484  /* the implication was redundant: the inverse is also redundant */
9485  return SCIP_OKAY;
9486  }
9487 
9488  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9489 
9490  /* check, whether implied variable is binary */
9491  if( !SCIPvarIsBinary(implvar) )
9492  {
9493  SCIP_Real lb;
9494  SCIP_Real ub;
9495 
9496  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9497  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9498  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9499  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9500  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9501  * for numerical reasons, ignore variable bounds with large absolute coefficient
9502  */
9503  lb = SCIPvarGetLbGlobal(implvar);
9504  ub = SCIPvarGetUbGlobal(implvar);
9505  if( impltype == SCIP_BOUNDTYPE_UPPER )
9506  {
9507  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9508  {
9509  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9510  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9511  }
9512  }
9513  else
9514  {
9515  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9516  {
9517  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9518  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9519  }
9520  }
9521  }
9522 
9523  return SCIP_OKAY;
9524 }
9525 
9526 /** adds transitive closure for binary implication x = a -> y = b */
9527 static
9529  SCIP_VAR* var, /**< problem variable */
9530  BMS_BLKMEM* blkmem, /**< block memory */
9531  SCIP_SET* set, /**< global SCIP settings */
9532  SCIP_STAT* stat, /**< problem statistics */
9533  SCIP_PROB* transprob, /**< transformed problem */
9534  SCIP_PROB* origprob, /**< original problem */
9535  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9536  SCIP_REOPT* reopt, /**< reoptimization data structure */
9537  SCIP_LP* lp, /**< current LP data */
9538  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9539  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9540  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9541  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9542  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9543  SCIP_Bool implvarfixing, /**< fixing b in implication */
9544  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9545  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9546  )
9547 {
9548  SCIP_VAR** implvars;
9549  SCIP_BOUNDTYPE* impltypes;
9550  SCIP_Real* implbounds;
9551  int nimpls;
9552  int i;
9553 
9554  *infeasible = FALSE;
9555 
9556  /* binary variable: implications of implvar */
9557  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9558  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9559  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9560  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9561 
9562  /* if variable has too many implications, the implication graph may become too dense */
9563  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9564 
9565  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9566  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9567  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9568  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9569  * only thing that can happen is that we add the same implication twice - this does no harm
9570  */
9571  while ( i >= 0 && !(*infeasible) )
9572  {
9573  SCIP_Bool added;
9574 
9575  assert(implvars[i] != implvar);
9576 
9577  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9578  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9579  */
9580  if( SCIPvarIsActive(implvars[i]) )
9581  {
9582  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9583  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9584  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9585  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9586  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9587  }
9588  --i;
9589  }
9590 
9591  return SCIP_OKAY;
9592 }
9593 
9594 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9595  * implication to the variable's implication list;
9596  * if the implication is conflicting, the variable is fixed to the opposite value;
9597  * if the variable is already fixed to the given value, the implication is performed immediately;
9598  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9599  */
9600 static
9602  SCIP_VAR* var, /**< problem variable */
9603  BMS_BLKMEM* blkmem, /**< block memory */
9604  SCIP_SET* set, /**< global SCIP settings */
9605  SCIP_STAT* stat, /**< problem statistics */
9606  SCIP_PROB* transprob, /**< transformed problem */
9607  SCIP_PROB* origprob, /**< original problem */
9608  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9609  SCIP_REOPT* reopt, /**< reoptimization data structure */
9610  SCIP_LP* lp, /**< current LP data */
9611  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9612  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9613  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9614  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9615  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9616  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9617  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9618  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9619  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9620  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9621  )
9622 {
9623  SCIP_Bool added;
9624 
9625  assert(var != NULL);
9626  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9627  assert(SCIPvarIsActive(var));
9628  assert(implvar != NULL);
9629  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9630  assert(infeasible != NULL);
9631 
9632  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9633  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9634  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9635 
9636  if( *infeasible || var == implvar || !transitive || !added )
9637  return SCIP_OKAY;
9638 
9639  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9640 
9641  /* add transitive closure */
9642  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9643  {
9644  SCIP_Bool implvarfixing;
9645 
9646  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9647 
9648  /* binary variable: implications of implvar */
9649  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9650  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9651 
9652  /* inverse implication */
9653  if( !(*infeasible) )
9654  {
9655  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9656  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9657  }
9658  }
9659  else
9660  {
9661  /* non-binary variable: variable lower bounds of implvar */
9662  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9663  {
9664  SCIP_VAR** vlbvars;
9665  SCIP_Real* vlbcoefs;
9666  SCIP_Real* vlbconstants;
9667  int nvlbvars;
9668  int i;
9669 
9670  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9671  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9672  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9673  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9674 
9675  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9676  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9677  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9678  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9679  * is that we add the same implication twice - this does no harm
9680  */
9681  i = nvlbvars-1;
9682  while ( i >= 0 && !(*infeasible) )
9683  {
9684  assert(vlbvars[i] != implvar);
9685  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9686 
9687  /* we have x == varfixing -> y <= b and y >= c*z + d:
9688  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9689  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9690  *
9691  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9692  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9693  * aggregation variable (the one which will stay active);
9694  *
9695  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9696  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9697  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9698  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9699  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9700  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9701  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9702  * have to explicitly check that the active variable has not a variable status
9703  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9704  */
9705  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9706  {
9707  SCIP_Real vbimplbound;
9708 
9709  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9710  if( vlbcoefs[i] >= 0.0 )
9711  {
9712  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9713  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9714  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9715  infeasible, nbdchgs, &added) );
9716  }
9717  else
9718  {
9719  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9720  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9721  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9722  infeasible, nbdchgs, &added) );
9723  }
9724  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9725  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9726  }
9727  --i;
9728  }
9729  }
9730 
9731  /* non-binary variable: variable upper bounds of implvar */
9732  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9733  {
9734  SCIP_VAR** vubvars;
9735  SCIP_Real* vubcoefs;
9736  SCIP_Real* vubconstants;
9737  int nvubvars;
9738  int i;
9739 
9740  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9741  vubvars = SCIPvboundsGetVars(implvar->vubs);
9742  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9743  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9744 
9745  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9746  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9747  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9748  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9749  * is that we add the same implication twice - this does no harm
9750  */
9751  i = nvubvars-1;
9752  while ( i >= 0 && !(*infeasible) )
9753  {
9754  assert(vubvars[i] != implvar);
9755  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9756 
9757  /* we have x == varfixing -> y >= b and y <= c*z + d:
9758  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9759  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9760  *
9761  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9762  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9763  * aggregation variable (the one which will stay active);
9764  *
9765  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9766  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9767  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9768  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9769  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9770  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9771  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9772  * have to explicitly check that the active variable has not a variable status
9773  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9774  */
9775  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9776  {
9777  SCIP_Real vbimplbound;
9778 
9779  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9780  if( vubcoefs[i] >= 0.0 )
9781  {
9782  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9783  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9784  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9785  infeasible, nbdchgs, &added) );
9786  }
9787  else
9788  {
9789  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9790  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9791  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9792  infeasible, nbdchgs, &added) );
9793  }
9794  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9795  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9796  }
9797  --i;
9798  }
9799  }
9800  }
9801 
9802  return SCIP_OKAY;
9803 }
9804 
9805 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9806  * if z is binary, the corresponding valid implication for z is also added;
9807  * improves the global bounds of the variable and the vlb variable if possible
9808  */
9810  SCIP_VAR* var, /**< problem variable */
9811  BMS_BLKMEM* blkmem, /**< block memory */
9812  SCIP_SET* set, /**< global SCIP settings */
9813  SCIP_STAT* stat, /**< problem statistics */
9814  SCIP_PROB* transprob, /**< transformed problem */
9815  SCIP_PROB* origprob, /**< original problem */
9816  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9817  SCIP_REOPT* reopt, /**< reoptimization data structure */
9818  SCIP_LP* lp, /**< current LP data */
9819  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9820  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9821  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9822  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9823  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9824  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9825  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9826  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9827  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9828  )
9829 {
9830  assert(var != NULL);
9831  assert(set != NULL);
9832  assert(var->scip == set->scip);
9833  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9834  assert(infeasible != NULL);
9835 
9836  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9837 
9838  *infeasible = FALSE;
9839  if( nbdchgs != NULL )
9840  *nbdchgs = 0;
9841 
9842  switch( SCIPvarGetStatus(var) )
9843  {
9845  assert(var->data.original.transvar != NULL);
9846  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9847  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9848  break;
9849 
9850  case SCIP_VARSTATUS_COLUMN:
9851  case SCIP_VARSTATUS_LOOSE:
9852  case SCIP_VARSTATUS_FIXED:
9853  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9854  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9855  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9856 
9857  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9858  if( SCIPsetIsZero(set, vlbcoef) )
9859  {
9860  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9861  *infeasible = TRUE;
9862  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9863  {
9864  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9865  * with the local bound, in this case we need to store the bound change as pending bound change
9866  */
9867  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9868  {
9869  assert(tree != NULL);
9870  assert(transprob != NULL);
9871  assert(SCIPprobIsTransformed(transprob));
9872 
9873  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9874  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9875  }
9876  else
9877  {
9878  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9879  }
9880 
9881  if( nbdchgs != NULL )
9882  (*nbdchgs)++;
9883  }
9884  }
9885  else if( var == vlbvar )
9886  {
9887  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
9888  if( SCIPsetIsEQ(set, vlbcoef, 1.0) )
9889  {
9890  if( SCIPsetIsPositive(set, vlbconstant) )
9891  *infeasible = TRUE;
9892  return SCIP_OKAY;
9893  }
9894  else
9895  {
9896  SCIP_Real lb = SCIPvarGetLbGlobal(var);
9897  SCIP_Real ub = SCIPvarGetUbGlobal(var);
9898 
9899  /* the variable bound constraint defines a new upper bound */
9900  if( SCIPsetIsGT(set, vlbcoef, 1.0) )
9901  {
9902  SCIP_Real newub = vlbconstant / (1.0 - vlbcoef);
9903 
9904  if( SCIPsetIsFeasLT(set, newub, lb) )
9905  {
9906  *infeasible = TRUE;
9907  return SCIP_OKAY;
9908  }
9909  else if( SCIPsetIsFeasLT(set, newub, ub) )
9910  {
9911  /* bound might be adjusted due to integrality condition */
9912  newub = adjustedUb(set, SCIPvarGetType(var), newub);
9913 
9914  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9915  * with the local bound, in this case we need to store the bound change as pending bound change
9916  */
9917  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9918  {
9919  assert(tree != NULL);
9920  assert(transprob != NULL);
9921  assert(SCIPprobIsTransformed(transprob));
9922 
9923  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9924  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9925  }
9926  else
9927  {
9928  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
9929  }
9930 
9931  if( nbdchgs != NULL )
9932  (*nbdchgs)++;
9933  }
9934  }
9935  /* the variable bound constraint defines a new lower bound */
9936  else
9937  {
9938  SCIP_Real newlb;
9939 
9940  assert(SCIPsetIsLT(set, vlbcoef, 1.0));
9941 
9942  newlb = vlbconstant / (1.0 - vlbcoef);
9943 
9944  if( SCIPsetIsFeasGT(set, newlb, ub) )
9945  {
9946  *infeasible = TRUE;
9947  return SCIP_OKAY;
9948  }
9949  else if( SCIPsetIsFeasGT(set, newlb, lb) )
9950  {
9951  /* bound might be adjusted due to integrality condition */
9952  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
9953 
9954  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9955  * with the local bound, in this case we need to store the bound change as pending bound change
9956  */
9957  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9958  {
9959  assert(tree != NULL);
9960  assert(transprob != NULL);
9961  assert(SCIPprobIsTransformed(transprob));
9962 
9963  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9964  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9965  }
9966  else
9967  {
9968  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
9969  }
9970 
9971  if( nbdchgs != NULL )
9972  (*nbdchgs)++;
9973  }
9974  }
9975  }
9976  }
9977  else if( SCIPvarIsActive(vlbvar) )
9978  {
9979  SCIP_Real xlb;
9980  SCIP_Real xub;
9981  SCIP_Real zlb;
9982  SCIP_Real zub;
9983  SCIP_Real minvlb;
9984  SCIP_Real maxvlb;
9985 
9987  assert(vlbcoef != 0.0);
9988 
9989  minvlb = -SCIPsetInfinity(set);
9990  maxvlb = SCIPsetInfinity(set);
9991 
9992  xlb = SCIPvarGetLbGlobal(var);
9993  xub = SCIPvarGetUbGlobal(var);
9994  zlb = SCIPvarGetLbGlobal(vlbvar);
9995  zub = SCIPvarGetUbGlobal(vlbvar);
9996 
9997  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9998  if( vlbcoef >= 0.0 )
9999  {
10000  SCIP_Real newzub;
10001 
10002  if( !SCIPsetIsInfinity(set, xub) )
10003  {
10004  /* x >= b*z + d -> z <= (x-d)/b */
10005  newzub = (xub - vlbconstant)/vlbcoef;
10006 
10007  /* return if the new bound is less than -infinity */
10008  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
10009  return SCIP_OKAY;
10010 
10011  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10012  {
10013  *infeasible = TRUE;
10014  return SCIP_OKAY;
10015  }
10016  if( SCIPsetIsFeasLT(set, newzub, zub) )
10017  {
10018  /* bound might be adjusted due to integrality condition */
10019  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
10020 
10021  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10022  * with the local bound, in this case we need to store the bound change as pending bound change
10023  */
10024  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10025  {
10026  assert(tree != NULL);
10027  assert(transprob != NULL);
10028  assert(SCIPprobIsTransformed(transprob));
10029 
10030  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10031  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10032  }
10033  else
10034  {
10035  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10036  }
10037  zub = newzub;
10038 
10039  if( nbdchgs != NULL )
10040  (*nbdchgs)++;
10041  }
10042  maxvlb = vlbcoef * zub + vlbconstant;
10043  if( !SCIPsetIsInfinity(set, -zlb) )
10044  minvlb = vlbcoef * zlb + vlbconstant;
10045  }
10046  else
10047  {
10048  if( !SCIPsetIsInfinity(set, zub) )
10049  maxvlb = vlbcoef * zub + vlbconstant;
10050  if( !SCIPsetIsInfinity(set, -zlb) )
10051  minvlb = vlbcoef * zlb + vlbconstant;
10052  }
10053  }
10054  else
10055  {
10056  SCIP_Real newzlb;
10057 
10058  if( !SCIPsetIsInfinity(set, xub) )
10059  {
10060  /* x >= b*z + d -> z >= (x-d)/b */
10061  newzlb = (xub - vlbconstant)/vlbcoef;
10062 
10063  /* return if the new bound is larger than infinity */
10064  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
10065  return SCIP_OKAY;
10066 
10067  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10068  {
10069  *infeasible = TRUE;
10070  return SCIP_OKAY;
10071  }
10072  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10073  {
10074  /* bound might be adjusted due to integrality condition */
10075  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
10076 
10077  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10078  * with the local bound, in this case we need to store the bound change as pending bound change
10079  */
10080  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10081  {
10082  assert(tree != NULL);
10083  assert(transprob != NULL);
10084  assert(SCIPprobIsTransformed(transprob));
10085 
10086  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10087  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10088  }
10089  else
10090  {
10091  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10092  }
10093  zlb = newzlb;
10094 
10095  if( nbdchgs != NULL )
10096  (*nbdchgs)++;
10097  }
10098  maxvlb = vlbcoef * zlb + vlbconstant;
10099  if( !SCIPsetIsInfinity(set, zub) )
10100  minvlb = vlbcoef * zub + vlbconstant;
10101  }
10102  else
10103  {
10104  if( !SCIPsetIsInfinity(set, -zlb) )
10105  maxvlb = vlbcoef * zlb + vlbconstant;
10106  if( !SCIPsetIsInfinity(set, zub) )
10107  minvlb = vlbcoef * zub + vlbconstant;
10108  }
10109  }
10110  if( maxvlb < minvlb )
10111  maxvlb = minvlb;
10112 
10113  /* adjust bounds due to integrality of variable */
10114  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10115  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
10116 
10117  /* check bounds for feasibility */
10118  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
10119  {
10120  *infeasible = TRUE;
10121  return SCIP_OKAY;
10122  }
10123  /* improve global lower bound of variable */
10124  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
10125  {
10126  /* bound might be adjusted due to integrality condition */
10127  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
10128 
10129  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10130  * with the local bound, in this case we need to store the bound change as pending bound change
10131  */
10132  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10133  {
10134  assert(tree != NULL);
10135  assert(transprob != NULL);
10136  assert(SCIPprobIsTransformed(transprob));
10137 
10138  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10139  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10140  }
10141  else
10142  {
10143  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
10144  }
10145  xlb = minvlb;
10146 
10147  if( nbdchgs != NULL )
10148  (*nbdchgs)++;
10149  }
10150  minvlb = xlb;
10151 
10152  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
10153  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10154  {
10155  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
10156  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
10157  */
10158 
10159  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
10160 
10161  if( vlbcoef >= 0.0 )
10162  {
10163  vlbcoef = maxvlb - minvlb;
10164  vlbconstant = minvlb;
10165  }
10166  else
10167  {
10168  vlbcoef = minvlb - maxvlb;
10169  vlbconstant = maxvlb;
10170  }
10171  }
10172 
10173  /* add variable bound to the variable bounds list */
10174  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
10175  {
10176  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10177  assert(!SCIPsetIsZero(set, vlbcoef));
10178 
10179  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10180  * list, thereby also adding the variable bound (or implication) to the other variable
10181  */
10182  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
10183  {
10184  /* add corresponding implication:
10185  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
10186  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
10187  */
10188  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10189  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
10190  infeasible, nbdchgs) );
10191  }
10192  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10193  {
10194  /* add corresponding implication:
10195  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
10196  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
10197  */
10198  SCIP_Real implbound;
10199  implbound = -vlbconstant/vlbcoef;
10200 
10201  /* tighten the implication bound if the variable is integer */
10202  if( SCIPvarIsIntegral(vlbvar) )
10203  {
10204  if( vlbcoef >= 0 )
10205  implbound = SCIPsetFloor(set, implbound);
10206  else
10207  implbound = SCIPsetCeil(set, implbound);
10208  }
10209  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10210  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
10211  implbound, transitive, infeasible, nbdchgs) );
10212  }
10213  else
10214  {
10215  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
10216  }
10217  }
10218  }
10219  break;
10220 
10222  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
10223  * y <= b/a * z + (d-c)/a, if a < 0
10224  */
10225  assert(var->data.aggregate.var != NULL);
10226  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10227  {
10228  /* a > 0 -> add variable lower bound */
10229  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10230  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10231  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10232  }
10233  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10234  {
10235  /* a < 0 -> add variable upper bound */
10236  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10237  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
10238  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10239  }
10240  else
10241  {
10242  SCIPerrorMessage("scalar is zero in aggregation\n");
10243  return SCIP_INVALIDDATA;
10244  }
10245  break;
10246 
10248  /* nothing to do here */
10249  break;
10250 
10252  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
10253  assert(var->negatedvar != NULL);
10255  assert(var->negatedvar->negatedvar == var);
10256  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10257  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
10258  nbdchgs) );
10259  break;
10260 
10261  default:
10262  SCIPerrorMessage("unknown variable status\n");
10263  return SCIP_INVALIDDATA;
10264  }
10265 
10266  return SCIP_OKAY;
10267 }
10268 
10269 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10270  * if z is binary, the corresponding valid implication for z is also added;
10271  * updates the global bounds of the variable and the vub variable correspondingly
10272  */
10274  SCIP_VAR* var, /**< problem variable */
10275  BMS_BLKMEM* blkmem, /**< block memory */
10276  SCIP_SET* set, /**< global SCIP settings */
10277  SCIP_STAT* stat, /**< problem statistics */
10278  SCIP_PROB* transprob, /**< transformed problem */
10279  SCIP_PROB* origprob, /**< original problem */
10280  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10281  SCIP_REOPT* reopt, /**< reoptimization data structure */
10282  SCIP_LP* lp, /**< current LP data */
10283  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10284  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10285  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10286  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10287  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10288  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10289  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10290  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10291  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10292  )
10293 {
10294  assert(var != NULL);
10295  assert(set != NULL);
10296  assert(var->scip == set->scip);
10297  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10298  assert(infeasible != NULL);
10299 
10300  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10301 
10302  *infeasible = FALSE;
10303  if( nbdchgs != NULL )
10304  *nbdchgs = 0;
10305 
10306  switch( SCIPvarGetStatus(var) )
10307  {
10309  assert(var->data.original.transvar != NULL);
10310  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10311  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10312  break;
10313 
10314  case SCIP_VARSTATUS_COLUMN:
10315  case SCIP_VARSTATUS_LOOSE:
10316  case SCIP_VARSTATUS_FIXED:
10317  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10318  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10319  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10320  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10321 
10322  /* if the vub coefficient is zero, just update the upper bound of the variable */
10323  if( SCIPsetIsZero(set, vubcoef) )
10324  {
10325  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10326  *infeasible = TRUE;
10327  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10328  {
10329  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10330  * with the local bound, in this case we need to store the bound change as pending bound change
10331  */
10332  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10333  {
10334  assert(tree != NULL);
10335  assert(transprob != NULL);
10336  assert(SCIPprobIsTransformed(transprob));
10337 
10338  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10339  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10340  }
10341  else
10342  {
10343  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10344  }
10345 
10346  if( nbdchgs != NULL )
10347  (*nbdchgs)++;
10348  }
10349  }
10350  else if( var == vubvar )
10351  {
10352  /* the variables cancels out, the variable bound constraint is either redundant or proves global infeasibility */
10353  if( SCIPsetIsEQ(set, vubcoef, 1.0) )
10354  {
10355  if( SCIPsetIsNegative(set, vubconstant) )
10356  *infeasible = TRUE;
10357  return SCIP_OKAY;
10358  }
10359  else
10360  {
10361  SCIP_Real lb = SCIPvarGetLbGlobal(var);
10362  SCIP_Real ub = SCIPvarGetUbGlobal(var);
10363 
10364  /* the variable bound constraint defines a new lower bound */
10365  if( SCIPsetIsGT(set, vubcoef, 1.0) )
10366  {
10367  SCIP_Real newlb = vubconstant / (1.0 - vubcoef);
10368 
10369  if( SCIPsetIsFeasGT(set, newlb, ub) )
10370  {
10371  *infeasible = TRUE;
10372  return SCIP_OKAY;
10373  }
10374  else if( SCIPsetIsFeasGT(set, newlb, lb) )
10375  {
10376  /* bound might be adjusted due to integrality condition */
10377  newlb = adjustedLb(set, SCIPvarGetType(var), newlb);
10378 
10379  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10380  * with the local bound, in this case we need to store the bound change as pending bound change
10381  */
10382  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10383  {
10384  assert(tree != NULL);
10385  assert(transprob != NULL);
10386  assert(SCIPprobIsTransformed(transprob));
10387 
10388  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10389  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10390  }
10391  else
10392  {
10393  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newlb) );
10394  }
10395 
10396  if( nbdchgs != NULL )
10397  (*nbdchgs)++;
10398  }
10399  }
10400  /* the variable bound constraint defines a new upper bound */
10401  else
10402  {
10403  SCIP_Real newub;
10404 
10405  assert(SCIPsetIsLT(set, vubcoef, 1.0));
10406 
10407  newub = vubconstant / (1.0 - vubcoef);
10408 
10409  if( SCIPsetIsFeasLT(set, newub, lb) )
10410  {
10411  *infeasible = TRUE;
10412  return SCIP_OKAY;
10413  }
10414  else if( SCIPsetIsFeasLT(set, newub, ub) )
10415  {
10416  /* bound might be adjusted due to integrality condition */
10417  newub = adjustedUb(set, SCIPvarGetType(var), newub);
10418 
10419  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10420  * with the local bound, in this case we need to store the bound change as pending bound change
10421  */
10422  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10423  {
10424  assert(tree != NULL);
10425  assert(transprob != NULL);
10426  assert(SCIPprobIsTransformed(transprob));
10427 
10428  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10429  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, newub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10430  }
10431  else
10432  {
10433  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newub) );
10434  }
10435 
10436  if( nbdchgs != NULL )
10437  (*nbdchgs)++;
10438  }
10439  }
10440  }
10441  }
10442  else if( SCIPvarIsActive(vubvar) )
10443  {
10444  SCIP_Real xlb;
10445  SCIP_Real xub;
10446  SCIP_Real zlb;
10447  SCIP_Real zub;
10448  SCIP_Real minvub;
10449  SCIP_Real maxvub;
10450 
10452  assert(vubcoef != 0.0);
10453 
10454  minvub = -SCIPsetInfinity(set);
10455  maxvub = SCIPsetInfinity(set);
10456 
10457  xlb = SCIPvarGetLbGlobal(var);
10458  xub = SCIPvarGetUbGlobal(var);
10459  zlb = SCIPvarGetLbGlobal(vubvar);
10460  zub = SCIPvarGetUbGlobal(vubvar);
10461 
10462  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10463  if( vubcoef >= 0.0 )
10464  {
10465  SCIP_Real newzlb;
10466 
10467  if( !SCIPsetIsInfinity(set, -xlb) )
10468  {
10469  /* x <= b*z + d -> z >= (x-d)/b */
10470  newzlb = (xlb - vubconstant)/vubcoef;
10471  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10472  {
10473  *infeasible = TRUE;
10474  return SCIP_OKAY;
10475  }
10476  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10477  {
10478  /* bound might be adjusted due to integrality condition */
10479  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10480 
10481  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10482  * with the local bound, in this case we need to store the bound change as pending bound change
10483  */
10484  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10485  {
10486  assert(tree != NULL);
10487  assert(transprob != NULL);
10488  assert(SCIPprobIsTransformed(transprob));
10489 
10490  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10491  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10492  }
10493  else
10494  {
10495  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10496  }
10497  zlb = newzlb;
10498 
10499  if( nbdchgs != NULL )
10500  (*nbdchgs)++;
10501  }
10502  minvub = vubcoef * zlb + vubconstant;
10503  if( !SCIPsetIsInfinity(set, zub) )
10504  maxvub = vubcoef * zub + vubconstant;
10505  }
10506  else
10507  {
10508  if( !SCIPsetIsInfinity(set, zub) )
10509  maxvub = vubcoef * zub + vubconstant;
10510  if( !SCIPsetIsInfinity(set, -zlb) )
10511  minvub = vubcoef * zlb + vubconstant;
10512  }
10513  }
10514  else
10515  {
10516  SCIP_Real newzub;
10517 
10518  if( !SCIPsetIsInfinity(set, -xlb) )
10519  {
10520  /* x <= b*z + d -> z <= (x-d)/b */
10521  newzub = (xlb - vubconstant)/vubcoef;
10522  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10523  {
10524  *infeasible = TRUE;
10525  return SCIP_OKAY;
10526  }
10527  if( SCIPsetIsFeasLT(set, newzub, zub) )
10528  {
10529  /* bound might be adjusted due to integrality condition */
10530  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10531 
10532  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10533  * with the local bound, in this case we need to store the bound change as pending bound change
10534  */
10535  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10536  {
10537  assert(tree != NULL);
10538  assert(transprob != NULL);
10539  assert(SCIPprobIsTransformed(transprob));
10540 
10541  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10542  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10543  }
10544  else
10545  {
10546  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10547  }
10548  zub = newzub;
10549 
10550  if( nbdchgs != NULL )
10551  (*nbdchgs)++;
10552  }
10553  minvub = vubcoef * zub + vubconstant;
10554  if( !SCIPsetIsInfinity(set, -zlb) )
10555  maxvub = vubcoef * zlb + vubconstant;
10556  }
10557  else
10558  {
10559  if( !SCIPsetIsInfinity(set, zub) )
10560  minvub = vubcoef * zub + vubconstant;
10561  if( !SCIPsetIsInfinity(set, -zlb) )
10562  maxvub = vubcoef * zlb + vubconstant;
10563  }
10564  }
10565  if( minvub > maxvub )
10566  minvub = maxvub;
10567 
10568  /* adjust bounds due to integrality of vub variable */
10569  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10570  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10571 
10572  /* check bounds for feasibility */
10573  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10574  {
10575  *infeasible = TRUE;
10576  return SCIP_OKAY;
10577  }
10578 
10579  /* improve global upper bound of variable */
10580  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10581  {
10582  /* bound might be adjusted due to integrality condition */
10583  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10584 
10585  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10586  * with the local bound, in this case we need to store the bound change as pending bound change
10587  */
10588  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10589  {
10590  assert(tree != NULL);
10591  assert(transprob != NULL);
10592  assert(SCIPprobIsTransformed(transprob));
10593 
10594  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10595  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10596  }
10597  else
10598  {
10599  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10600  }
10601  xub = maxvub;
10602 
10603  if( nbdchgs != NULL )
10604  (*nbdchgs)++;
10605  }
10606  maxvub = xub;
10607 
10608  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10609  if( SCIPvarIsBinary(vubvar) )
10610  {
10611  /* b > 0: x <= (maxvub - minvub) * z + minvub
10612  * b < 0: x <= (minvub - maxvub) * z + maxvub
10613  */
10614 
10615  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10616 
10617  if( vubcoef >= 0.0 )
10618  {
10619  vubcoef = maxvub - minvub;
10620  vubconstant = minvub;
10621  }
10622  else
10623  {
10624  vubcoef = minvub - maxvub;
10625  vubconstant = maxvub;
10626  }
10627  }
10628 
10629  /* add variable bound to the variable bounds list */
10630  if( SCIPsetIsFeasLT(set, minvub, xub) )
10631  {
10632  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10633  assert(!SCIPsetIsZero(set, vubcoef));
10634 
10635  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10636  * list, thereby also adding the variable bound (or implication) to the other variable
10637  */
10638  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10639  {
10640  /* add corresponding implication:
10641  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10642  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10643  */
10644  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10645  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10646  infeasible, nbdchgs) );
10647  }
10648  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10649  {
10650  /* add corresponding implication:
10651  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10652  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10653  */
10654  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10655  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10656  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10657  }
10658  else
10659  {
10660  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10661  }
10662  }
10663  }
10664  break;
10665 
10667  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10668  * y >= b/a * z + (d-c)/a, if a < 0
10669  */
10670  assert(var->data.aggregate.var != NULL);
10671  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10672  {
10673  /* a > 0 -> add variable upper bound */
10674  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10675  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10676  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10677  }
10678  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10679  {
10680  /* a < 0 -> add variable lower bound */
10681  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10682  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10683  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10684  }
10685  else
10686  {
10687  SCIPerrorMessage("scalar is zero in aggregation\n");
10688  return SCIP_INVALIDDATA;
10689  }
10690  break;
10691 
10693  /* nothing to do here */
10694  break;
10695 
10697  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10698  assert(var->negatedvar != NULL);
10700  assert(var->negatedvar->negatedvar == var);
10701  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10702  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10703  nbdchgs) );
10704  break;
10705 
10706  default:
10707  SCIPerrorMessage("unknown variable status\n");
10708  return SCIP_INVALIDDATA;
10709  }
10710 
10711  return SCIP_OKAY;
10712 }
10713 
10714 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10715  * also adds the corresponding implication or variable bound to the implied variable;
10716  * if the implication is conflicting, the variable is fixed to the opposite value;
10717  * if the variable is already fixed to the given value, the implication is performed immediately;
10718  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10719  */
10721  SCIP_VAR* var, /**< problem variable */
10722  BMS_BLKMEM* blkmem, /**< block memory */
10723  SCIP_SET* set, /**< global SCIP settings */
10724  SCIP_STAT* stat, /**< problem statistics */
10725  SCIP_PROB* transprob, /**< transformed problem */
10726  SCIP_PROB* origprob, /**< original problem */
10727  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10728  SCIP_REOPT* reopt, /**< reoptimization data structure */
10729  SCIP_LP* lp, /**< current LP data */
10730  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10731  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10732  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10733  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10734  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10735  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10736  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10737  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10738  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10739  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10740  )
10741 {
10742  assert(var != NULL);
10743  assert(set != NULL);
10744  assert(var->scip == set->scip);
10745  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10746  assert(infeasible != NULL);
10747 
10748  *infeasible = FALSE;
10749  if( nbdchgs != NULL )
10750  *nbdchgs = 0;
10751 
10752  switch( SCIPvarGetStatus(var) )
10753  {
10755  assert(var->data.original.transvar != NULL);
10756  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10757  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10758  nbdchgs) );
10759  break;
10760 
10761  case SCIP_VARSTATUS_COLUMN:
10762  case SCIP_VARSTATUS_LOOSE:
10763  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10764  * the variable, the implication can be applied directly;
10765  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10766  */
10767  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10768  {
10769  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10770  {
10771  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10772  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10773  }
10774  }
10775  else
10776  {
10777  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10778  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10779  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10780  {
10781  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10782  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10783  }
10784  }
10785  break;
10786 
10787  case SCIP_VARSTATUS_FIXED:
10788  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10789  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10790  {
10791  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10792  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10793  }
10794  break;
10795 
10797  /* implication added for x == 1:
10798  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10799  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10800  * implication added for x == 0:
10801  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10802  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10803  *
10804  * use only binary variables z
10805  */
10806  assert(var->data.aggregate.var != NULL);
10807  if( SCIPvarIsBinary(var->data.aggregate.var) )
10808  {
10809  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10810  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10811 
10812  if( var->data.aggregate.scalar > 0 )
10813  {
10814  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10815  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10816  nbdchgs) );
10817  }
10818  else
10819  {
10820  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10821  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10822  nbdchgs) );
10823  }
10824  }
10825  break;
10826 
10828  /* nothing to do here */
10829  break;
10830 
10832  /* implication added for x == 1:
10833  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10834  * implication added for x == 0:
10835  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10836  */
10837  assert(var->negatedvar != NULL);
10839  assert(var->negatedvar->negatedvar == var);
10840  assert(SCIPvarIsBinary(var->negatedvar));
10841 
10843  {
10844  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10845  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10846  }
10847  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10848  else
10849  {
10850  /* if the implied variable is of binary type exchange the variables */
10851  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10852  {
10853  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10854  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10855  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10856  infeasible, nbdchgs) );
10857  }
10858  else
10859  {
10860  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10861  * implication as variable bounds
10862  */
10863 
10864  /* add variable lower bound on the negation of var */
10865  if( varfixing )
10866  {
10867  /* (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
10868  * as variable lower bound
10869  */
10870  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10871  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10872  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10873  }
10874  else
10875  {
10876  /* (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
10877  * as variable upper bound
10878  */
10879  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10880  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10881  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10882  }
10883 
10884  /* add variable bound on implvar */
10885  if( impltype == SCIP_BOUNDTYPE_UPPER )
10886  {
10887  /* (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
10888  * as variable upper bound
10889  */
10890  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10891  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10892  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10893  }
10894  else
10895  {
10896  /* (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
10897  * as variable upper bound
10898  */
10899  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10900  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10901  transitive, infeasible, nbdchgs) );
10902  }
10903  }
10904  }
10905  break;
10906 
10907  default:
10908  SCIPerrorMessage("unknown variable status\n");
10909  return SCIP_INVALIDDATA;
10910  }
10911 
10912  return SCIP_OKAY;
10913 }
10914 
10915 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10916  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10917  * both variables must be active, variable x must be binary
10918  */
10920  SCIP_VAR* var, /**< problem variable x */
10921  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10922  SCIP_VAR* implvar, /**< variable y to search for */
10923  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10924  )
10925 {
10926  assert(var != NULL);
10927  assert(implvar != NULL);
10928  assert(SCIPvarIsActive(var));
10929  assert(SCIPvarIsActive(implvar));
10930  assert(SCIPvarIsBinary(var));
10931 
10932  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10933 }
10934 
10935 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10936  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10937  * both variables must be active binary variables
10938  */
10940  SCIP_VAR* var, /**< problem variable x */
10941  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10942  SCIP_VAR* implvar, /**< variable y to search for */
10943  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10944  )
10945 {
10946  assert(SCIPvarIsBinary(implvar));
10947 
10948  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10949 }
10950 
10951 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10953  SCIP_VAR* var, /**< problem variable */
10954  BMS_BLKMEM* blkmem, /**< block memory */
10955  SCIP_SET* set, /**< global SCIP settings */
10956  SCIP_STAT* stat, /**< problem statistics */
10957  SCIP_PROB* transprob, /**< transformed problem */
10958  SCIP_PROB* origprob, /**< original problem */
10959  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10960  SCIP_REOPT* reopt, /**< reoptimization data structure */
10961  SCIP_LP* lp, /**< current LP data */
10962  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10963  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10964  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10965  SCIP_Bool value, /**< value to fix variable to */
10966  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10967  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10968  )
10969 {
10970  assert(var != NULL);
10971  assert(set != NULL);
10972  assert(var->scip == set->scip);
10973  assert(infeasible != NULL);
10974 
10975  *infeasible = FALSE;
10976 
10977  if( value == FALSE )
10978  {
10979  if( var->glbdom.lb > 0.5 )
10980  *infeasible = TRUE;
10981  else if( var->glbdom.ub > 0.5 )
10982  {
10983  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10984  * with the local bound, in this case we need to store the bound change as pending bound change
10985  */
10986  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10987  {
10988  assert(tree != NULL);
10989  assert(transprob != NULL);
10990  assert(SCIPprobIsTransformed(transprob));
10991 
10992  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10993  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10994  }
10995  else
10996  {
10997  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10998  }
10999 
11000  if( nbdchgs != NULL )
11001  (*nbdchgs)++;
11002  }
11003  }
11004  else
11005  {
11006  if( var->glbdom.ub < 0.5 )
11007  *infeasible = TRUE;
11008  else if( var->glbdom.lb < 0.5 )
11009  {
11010  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
11011  * with the local bound, in this case we need to store the bound change as pending bound change
11012  */
11013  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
11014  {
11015  assert(tree != NULL);
11016  assert(transprob != NULL);
11017  assert(SCIPprobIsTransformed(transprob));
11018 
11019  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
11020  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
11021  }
11022  else
11023  {
11024  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
11025  }
11026 
11027  if( nbdchgs != NULL )
11028  (*nbdchgs)++;
11029  }
11030  }
11031 
11032  /* during presolving, the variable should have been removed immediately from all its cliques */
11033  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
11034 
11035  return SCIP_OKAY;
11036 }
11037 
11038 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
11039  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
11040  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
11041  * the opposite of the value they take in the clique
11042  */
11044  SCIP_VAR* var, /**< problem variable */
11045  BMS_BLKMEM* blkmem, /**< block memory */
11046  SCIP_SET* set, /**< global SCIP settings */
11047  SCIP_STAT* stat, /**< problem statistics */
11048  SCIP_PROB* transprob, /**< transformed problem */
11049  SCIP_PROB* origprob, /**< original problem */
11050  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
11051  SCIP_REOPT* reopt, /**< reoptimization data structure */
11052  SCIP_LP* lp, /**< current LP data */
11053  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
11054  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
11055  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11056  SCIP_Bool value, /**< value of the variable in the clique */
11057  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
11058  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
11059  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
11060  )
11061 {
11062  assert(var != NULL);
11063  assert(set != NULL);
11064  assert(var->scip == set->scip);
11065  assert(SCIPvarIsBinary(var));
11066  assert(infeasible != NULL);
11067 
11068  *infeasible = FALSE;
11069 
11070  /* get corresponding active problem variable */
11071  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11076  assert(SCIPvarIsBinary(var));
11077 
11078  /* only column and loose variables may be member of a clique */
11080  {
11081  SCIP_Bool doubleentry;
11082  SCIP_Bool oppositeentry;
11083 
11084  /* add variable to clique */
11085  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
11086 
11087  /* add clique to variable's clique list */
11088  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11089 
11090  /* check consistency of cliquelist */
11091  SCIPcliquelistCheck(var->cliquelist, var);
11092 
11093  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
11094  if( doubleentry )
11095  {
11096  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11097  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
11098  }
11099 
11100  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
11101  * to the opposite of the value they take in the clique
11102  */
11103  if( oppositeentry )
11104  {
11105  SCIP_VAR** vars;
11106  SCIP_Bool* values;
11107  int nvars;
11108  int i;
11109 
11110  nvars = SCIPcliqueGetNVars(clique);
11111  vars = SCIPcliqueGetVars(clique);
11112  values = SCIPcliqueGetValues(clique);
11113  for( i = 0; i < nvars && !(*infeasible); ++i )
11114  {
11115  if( vars[i] == var )
11116  continue;
11117 
11118  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
11119  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
11120  }
11121  }
11122  }
11123 
11124  return SCIP_OKAY;
11125 }
11126 
11127 /** adds a filled clique to the cliquelists of all corresponding variables */
11129  SCIP_VAR** vars, /**< problem variables */
11130  SCIP_Bool* values, /**< values of the variables in the clique */
11131  int nvars, /**< number of problem variables */
11132  BMS_BLKMEM* blkmem, /**< block memory */
11133  SCIP_SET* set, /**< global SCIP settings */
11134  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
11135  )
11136 {
11137  SCIP_VAR* var;
11138  int v;
11139 
11140  assert(vars != NULL);
11141  assert(values != NULL);
11142  assert(nvars > 0);
11143  assert(set != NULL);
11144  assert(blkmem != NULL);
11145  assert(clique != NULL);
11146 
11147  for( v = nvars - 1; v >= 0; --v )
11148  {
11149  var = vars[v];
11150  assert(SCIPvarIsBinary(var));
11152 
11153  /* add clique to variable's clique list */
11154  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
11155 
11156  /* check consistency of cliquelist */
11157  SCIPcliquelistCheck(var->cliquelist, var);
11158  }
11159 
11160  return SCIP_OKAY;
11161 }
11162 
11163 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
11164  * itself
11165  */
11167  SCIP_VAR* var, /**< problem variable */
11168  BMS_BLKMEM* blkmem, /**< block memory */
11169  SCIP_SET* set, /**< global SCIP settings */
11170  SCIP_Bool value, /**< value of the variable in the clique */
11171  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11172  )
11173 {
11174  assert(var != NULL);
11175  assert(SCIPvarIsBinary(var));
11177 
11178  /* add clique to variable's clique list */
11179  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
11180 
11181  return SCIP_OKAY;
11182 }
11183 
11184 
11185 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
11186  * itself
11187  */
11189  SCIP_VAR* var, /**< problem variable */
11190  BMS_BLKMEM* blkmem, /**< block memory */
11191  SCIP_Bool value, /**< value of the variable in the clique */
11192  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
11193  )
11194 {
11195  assert(var != NULL);
11196  assert(SCIPvarIsBinary(var));
11197 
11198  /* delete clique from variable's clique list */
11199  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11200 
11201  return SCIP_OKAY;
11202 }
11203 
11204 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
11206  SCIP_VAR* var, /**< problem variable */
11207  BMS_BLKMEM* blkmem, /**< block memory */
11208  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
11209  SCIP_Bool value, /**< value of the variable in the clique */
11210  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
11211  )
11212 {
11213  assert(var != NULL);
11214  assert(SCIPvarIsBinary(var));
11215 
11216  /* get corresponding active problem variable */
11217  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
11222  assert(SCIPvarIsBinary(var));
11223 
11224  /* only column and loose variables may be member of a clique */
11226  {
11227  /* delete clique from variable's clique list */
11228  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
11229 
11230  /* delete variable from clique */
11231  SCIPcliqueDelVar(clique, cliquetable, var, value);
11232 
11233  /* check consistency of cliquelist */
11234  SCIPcliquelistCheck(var->cliquelist, var);
11235  }
11236 
11237  return SCIP_OKAY;
11238 }
11239 
11240 /** returns whether there is a clique that contains both given variable/value pairs;
11241  * the variables must be active binary variables;
11242  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
11243  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
11244  *
11245  * @note a variable with it's negated variable are NOT! in a clique
11246  * @note a variable with itself are in a clique
11247  */
11249  SCIP_VAR* var1, /**< first variable */
11250  SCIP_Bool value1, /**< value of first variable */
11251  SCIP_VAR* var2, /**< second variable */
11252  SCIP_Bool value2, /**< value of second variable */
11253  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
11254  )
11255 {
11256  assert(var1 != NULL);
11257  assert(var2 != NULL);
11258  assert(SCIPvarIsActive(var1));
11259  assert(SCIPvarIsActive(var2));
11260  assert(SCIPvarIsBinary(var1));
11261  assert(SCIPvarIsBinary(var2));
11262 
11263  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
11264  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
11265 }
11266 
11267 /** actually changes the branch factor of the variable and of all parent variables */
11268 static
11270  SCIP_VAR* var, /**< problem variable */
11271  SCIP_SET* set, /**< global SCIP settings */
11272  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11273  )
11274 {
11275  SCIP_VAR* parentvar;
11276  SCIP_Real eps;
11277  int i;
11278 
11279  assert(var != NULL);
11280  assert(set != NULL);
11281  assert(var->scip == set->scip);
11282 
11283  /* only use positive values */
11284  eps = SCIPsetEpsilon(set);
11285  branchfactor = MAX(branchfactor, eps);
11286 
11287  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
11288 
11289  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
11290  return SCIP_OKAY;
11291 
11292  /* change the branch factor */
11293  var->branchfactor = branchfactor;
11294 
11295  /* process parent variables */
11296  for( i = 0; i < var->nparentvars; ++i )
11297  {
11298  parentvar = var->parentvars[i];
11299  assert(parentvar != NULL);
11300 
11301  switch( SCIPvarGetStatus(parentvar) )
11302  {
11304  /* do not change priorities across the border between transformed and original problem */
11305  break;
11306 
11307  case SCIP_VARSTATUS_COLUMN:
11308  case SCIP_VARSTATUS_LOOSE:
11309  case SCIP_VARSTATUS_FIXED:
11311  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11312  SCIPABORT();
11313  return SCIP_INVALIDDATA; /*lint !e527*/
11314 
11317  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
11318  break;
11319 
11320  default:
11321  SCIPerrorMessage("unknown variable status\n");
11322  SCIPABORT();
11323  return SCIP_ERROR; /*lint !e527*/
11324  }
11325  }
11326 
11327  return SCIP_OKAY;
11328 }
11329 
11330 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
11331  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
11332  */
11334  SCIP_VAR* var, /**< problem variable */
11335  SCIP_SET* set, /**< global SCIP settings */
11336  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
11337  )
11338 {
11339  int v;
11340 
11341  assert(var != NULL);
11342  assert(set != NULL);
11343  assert(var->scip == set->scip);
11344  assert(branchfactor >= 0.0);
11345 
11346  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
11347 
11348  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
11349  return SCIP_OKAY;
11350 
11351  /* change priorities of attached variables */
11352  switch( SCIPvarGetStatus(var) )
11353  {
11355  if( var->data.original.transvar != NULL )
11356  {
11357  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
11358  }
11359  else
11360  {
11361  assert(set->stage == SCIP_STAGE_PROBLEM);
11362  var->branchfactor = branchfactor;
11363  }
11364  break;
11365 
11366  case SCIP_VARSTATUS_COLUMN:
11367  case SCIP_VARSTATUS_LOOSE:
11368  case SCIP_VARSTATUS_FIXED:
11369  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11370  break;
11371 
11373  assert(var->data.aggregate.var != NULL);
11374  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11375  break;
11376 
11378  assert(!var->donotmultaggr);
11379  for( v = 0; v < var->data.multaggr.nvars; ++v )
11380  {
11381  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11382  }
11383  break;
11384 
11386  assert(var->negatedvar != NULL);
11388  assert(var->negatedvar->negatedvar == var);
11389  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11390  break;
11391 
11392  default:
11393  SCIPerrorMessage("unknown variable status\n");
11394  SCIPABORT();
11395  return SCIP_ERROR; /*lint !e527*/
11396  }
11397 
11398  return SCIP_OKAY;
11399 }
11400 
11401 /** actually changes the branch priority of the variable and of all parent variables */
11402 static
11404  SCIP_VAR* var, /**< problem variable */
11405  int branchpriority /**< branching priority of the variable */
11406  )
11407 {
11408  SCIP_VAR* parentvar;
11409  int i;
11410 
11411  assert(var != NULL);
11412 
11413  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11414  var->name, var->branchpriority, branchpriority);
11415 
11416  if( branchpriority == var->branchpriority )
11417  return SCIP_OKAY;
11418 
11419  /* change the branch priority */
11420  var->branchpriority = branchpriority;
11421 
11422  /* process parent variables */
11423  for( i = 0; i < var->nparentvars; ++i )
11424  {
11425  parentvar = var->parentvars[i];
11426  assert(parentvar != NULL);
11427 
11428  switch( SCIPvarGetStatus(parentvar) )
11429  {
11431  /* do not change priorities across the border between transformed and original problem */
11432  break;
11433 
11434  case SCIP_VARSTATUS_COLUMN:
11435  case SCIP_VARSTATUS_LOOSE:
11436  case SCIP_VARSTATUS_FIXED:
11438  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11439  SCIPABORT();
11440  return SCIP_INVALIDDATA; /*lint !e527*/
11441 
11444  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11445  break;
11446 
11447  default:
11448  SCIPerrorMessage("unknown variable status\n");
11449  return SCIP_ERROR;
11450  }
11451  }
11452 
11453  return SCIP_OKAY;
11454 }
11455 
11456 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11457  * with lower priority in selection of branching variable
11458  */
11460  SCIP_VAR* var, /**< problem variable */
11461  int branchpriority /**< branching priority of the variable */
11462  )
11463 {
11464  int v;
11465 
11466  assert(var != NULL);
11467 
11468  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11469 
11470  if( var->branchpriority == branchpriority )
11471  return SCIP_OKAY;
11472 
11473  /* change priorities of attached variables */
11474  switch( SCIPvarGetStatus(var) )
11475  {
11477  if( var->data.original.transvar != NULL )
11478  {
11479  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11480  }
11481  else
11482  var->branchpriority = branchpriority;
11483  break;
11484 
11485  case SCIP_VARSTATUS_COLUMN:
11486  case SCIP_VARSTATUS_LOOSE:
11487  case SCIP_VARSTATUS_FIXED:
11488  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11489  break;
11490 
11492  assert(var->data.aggregate.var != NULL);
11493  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11494  break;
11495 
11497  assert(!var->donotmultaggr);
11498  for( v = 0; v < var->data.multaggr.nvars; ++v )
11499  {
11500  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11501  }
11502  break;
11503 
11505  assert(var->negatedvar != NULL);
11507  assert(var->negatedvar->negatedvar == var);
11508  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11509  break;
11510 
11511  default:
11512  SCIPerrorMessage("unknown variable status\n");
11513  SCIPABORT();
11514  return SCIP_ERROR; /*lint !e527*/
11515  }
11516 
11517  return SCIP_OKAY;
11518 }
11519 
11520 /** actually changes the branch direction of the variable and of all parent variables */
11521 static
11523  SCIP_VAR* var, /**< problem variable */
11524  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11525  )
11526 {
11527  SCIP_VAR* parentvar;
11528  int i;
11529 
11530  assert(var != NULL);
11531 
11532  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11533  var->name, var->branchdirection, branchdirection);
11534 
11535  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11536  return SCIP_OKAY;
11537 
11538  /* change the branch direction */
11539  var->branchdirection = branchdirection; /*lint !e641*/
11540 
11541  /* process parent variables */
11542  for( i = 0; i < var->nparentvars; ++i )
11543  {
11544  parentvar = var->parentvars[i];
11545  assert(parentvar != NULL);
11546 
11547  switch( SCIPvarGetStatus(parentvar) )
11548  {
11550  /* do not change directions across the border between transformed and original problem */
11551  break;
11552 
11553  case SCIP_VARSTATUS_COLUMN:
11554  case SCIP_VARSTATUS_LOOSE:
11555  case SCIP_VARSTATUS_FIXED:
11557  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11558  SCIPABORT();
11559  return SCIP_INVALIDDATA; /*lint !e527*/
11560 
11562  if( parentvar->data.aggregate.scalar > 0.0 )
11563  {
11564  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11565  }
11566  else
11567  {
11568  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11569  }
11570  break;
11571 
11573  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11574  break;
11575 
11576  default:
11577  SCIPerrorMessage("unknown variable status\n");
11578  SCIPABORT();
11579  return SCIP_ERROR; /*lint !e527*/
11580  }
11581  }
11582 
11583  return SCIP_OKAY;
11584 }
11585 
11586 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11587  * with lower direction in selection of branching variable
11588  */
11590  SCIP_VAR* var, /**< problem variable */
11591  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11592  )
11593 {
11594  int v;
11595 
11596  assert(var != NULL);
11597 
11598  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11599 
11600  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11601  return SCIP_OKAY;
11602 
11603  /* change directions of attached variables */
11604  switch( SCIPvarGetStatus(var) )
11605  {
11607  if( var->data.original.transvar != NULL )
11608  {
11609  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11610  }
11611  else
11612  var->branchdirection = branchdirection; /*lint !e641*/
11613  break;
11614 
11615  case SCIP_VARSTATUS_COLUMN:
11616  case SCIP_VARSTATUS_LOOSE:
11617  case SCIP_VARSTATUS_FIXED:
11618  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11619  break;
11620 
11622  assert(var->data.aggregate.var != NULL);
11623  if( var->data.aggregate.scalar > 0.0 )
11624  {
11625  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11626  }
11627  else
11628  {
11630  }
11631  break;
11632 
11634  assert(!var->donotmultaggr);
11635  for( v = 0; v < var->data.multaggr.nvars; ++v )
11636  {
11637  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11638  assert(var->data.multaggr.vars[v] != NULL);
11640  {
11641  if( var->data.multaggr.scalars[v] > 0.0 )
11642  {
11643  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11644  }
11645  else
11646  {
11648  }
11649  }
11650  }
11651  break;
11652 
11654  assert(var->negatedvar != NULL);
11656  assert(var->negatedvar->negatedvar == var);
11658  break;
11659 
11660  default:
11661  SCIPerrorMessage("unknown variable status\n");
11662  SCIPABORT();
11663  return SCIP_ERROR; /*lint !e527*/
11664  }
11665 
11666  return SCIP_OKAY;
11667 }
11668 
11669 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11670  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11671  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11672  * are equal, which means both variables are equal
11673  */
11675  SCIP_VAR* var1, /**< first problem variable */
11676  SCIP_VAR* var2 /**< second problem variable */
11677  )
11678 {
11679  assert(var1 != NULL);
11680  assert(var2 != NULL);
11683 
11685  var1 = SCIPvarGetNegatedVar(var1);
11687  var2 = SCIPvarGetNegatedVar(var2);
11688 
11689  assert(var1 != NULL);
11690  assert(var2 != NULL);
11691 
11692  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11693  return -1;
11694  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11695  return +1;
11696 
11697  assert(var1 == var2);
11698  return 0;
11699 }
11700 
11701 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11702  * variables are handled as the same variables
11703  */
11704 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11706  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11707 }
11708 
11709 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11710  * variable index; returns 0 if both indices are equal, which means both variables are equal
11711  */
11712 int SCIPvarCompare(
11713  SCIP_VAR* var1, /**< first problem variable */
11714  SCIP_VAR* var2 /**< second problem variable */
11715  )
11716 {
11717  assert(var1 != NULL);
11718  assert(var2 != NULL);
11719 
11720  if( var1->index < var2->index )
11721  return -1;
11722  else if( var1->index > var2->index )
11723  return +1;
11724  else
11725  {
11726  assert(var1 == var2);
11727  return 0;
11728  }
11729 }
11730 
11731 /** comparison method for sorting variables by non-decreasing index */
11732 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11734  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11735 }
11736 
11737 /** comparison method for sorting variables by non-decreasing objective coefficient */
11738 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11740  SCIP_Real obj1;
11741  SCIP_Real obj2;
11742 
11743  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11744  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11745 
11746  if( obj1 < obj2 )
11747  return -1;
11748  else if( obj1 > obj2 )
11749  return +1;
11750  else
11751  return 0;
11752 }
11753 
11754 /** hash key retrieval function for variables */
11755 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11756 { /*lint --e{715}*/
11757  return elem;
11758 }
11759 
11760 /** returns TRUE iff the indices of both variables are equal */
11761 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11762 { /*lint --e{715}*/
11763  if( key1 == key2 )
11764  return TRUE;
11765  return FALSE;
11766 }
11767 
11768 /** returns the hash value of the key */
11769 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11770 { /*lint --e{715}*/
11771  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11772  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11773 }
11774 
11775 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11777  SCIP_SET* set, /**< global SCIP settings */
11778  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11779  * variables, if enough slots exist
11780  */
11781  int* nvars, /**< number of given variables, and as output number of active variables,
11782  * if enough slots exist
11783  */
11784  int varssize, /**< available slots in vars array */
11785  int* requiredsize /**< pointer to store the required array size for the active variables */
11786  )
11787 {
11788  SCIP_VAR** activevars;
11789  int nactivevars;
11790  int activevarssize;
11791 
11792  SCIP_VAR* var;
11793  int v;
11794 
11795  SCIP_VAR** tmpvars;
11796  SCIP_VAR** multvars;
11797  int tmpvarssize;
11798  int ntmpvars;
11799  int noldtmpvars;
11800  int nmultvars;
11801 
11802  assert(set != NULL);
11803  assert(nvars != NULL);
11804  assert(vars != NULL || *nvars == 0);
11805  assert(varssize >= *nvars);
11806  assert(requiredsize != NULL);
11807 
11808  *requiredsize = 0;
11809 
11810  if( *nvars == 0 )
11811  return SCIP_OKAY;
11812 
11813  nactivevars = 0;
11814  activevarssize = *nvars;
11815  ntmpvars = *nvars;
11816  tmpvarssize = *nvars;
11817 
11818  /* temporary memory */
11819  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11820  /* coverity[copy_paste_error] */
11821  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11822 
11823  noldtmpvars = ntmpvars;
11824 
11825  /* sort all variables to combine equal variables easily */
11826  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11827  for( v = ntmpvars - 1; v > 0; --v )
11828  {
11829  /* combine same variables */
11830  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11831  {
11832  --ntmpvars;
11833  tmpvars[v] = tmpvars[ntmpvars];
11834  }
11835  }
11836  /* sort all variables again to combine equal variables later on */
11837  if( noldtmpvars > ntmpvars )
11838  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11839 
11840  /* collect for each variable the representation in active variables */
11841  while( ntmpvars >= 1 )
11842  {
11843  --ntmpvars;
11844  var = tmpvars[ntmpvars];
11845  assert( var != NULL );
11846 
11847  switch( SCIPvarGetStatus(var) )
11848  {
11850  if( var->data.original.transvar == NULL )
11851  {
11852  SCIPerrorMessage("original variable has no transformed variable attached\n");
11853  SCIPABORT();
11854  return SCIP_INVALIDDATA; /*lint !e527*/
11855  }
11856  tmpvars[ntmpvars] = var->data.original.transvar;
11857  ++ntmpvars;
11858  break;
11859 
11861  tmpvars[ntmpvars] = var->data.aggregate.var;
11862  ++ntmpvars;
11863  break;
11864 
11866  tmpvars[ntmpvars] = var->negatedvar;
11867  ++ntmpvars;
11868  break;
11869 
11870  case SCIP_VARSTATUS_LOOSE:
11871  case SCIP_VARSTATUS_COLUMN:
11872  /* check for space in temporary memory */
11873  if( nactivevars >= activevarssize )
11874  {
11875  activevarssize *= 2;
11876  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11877  assert(nactivevars < activevarssize);
11878  }
11879  activevars[nactivevars] = var;
11880  nactivevars++;
11881  break;
11882 
11884  /* x = a_1*y_1 + ... + a_n*y_n + c */
11885  nmultvars = var->data.multaggr.nvars;
11886  multvars = var->data.multaggr.vars;
11887 
11888  /* check for space in temporary memory */
11889  if( nmultvars + ntmpvars > tmpvarssize )
11890  {
11891  while( nmultvars + ntmpvars > tmpvarssize )
11892  tmpvarssize *= 2;
11893  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11894  assert(nmultvars + ntmpvars <= tmpvarssize);
11895  }
11896 
11897  /* copy all multi-aggregation variables into our working array */
11898  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11899 
11900  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11901  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11902 
11903  ntmpvars += nmultvars;
11904  noldtmpvars = ntmpvars;
11905 
11906  /* sort all variables to combine equal variables easily */
11907  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11908  for( v = ntmpvars - 1; v > 0; --v )
11909  {
11910  /* combine same variables */
11911  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11912  {
11913  --ntmpvars;
11914  tmpvars[v] = tmpvars[ntmpvars];
11915  }
11916  }
11917  /* sort all variables again to combine equal variables later on */
11918  if( noldtmpvars > ntmpvars )
11919  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11920 
11921  break;
11922 
11923  case SCIP_VARSTATUS_FIXED:
11924  /* no need for memorizing fixed variables */
11925  break;
11926 
11927  default:
11928  SCIPerrorMessage("unknown variable status\n");
11929  SCIPABORT();
11930  return SCIP_INVALIDDATA; /*lint !e527*/
11931  }
11932  }
11933 
11934  /* sort variable array by variable index */
11935  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11936 
11937  /* eliminate duplicates and count required size */
11938  v = nactivevars - 1;
11939  while( v > 0 )
11940  {
11941  /* combine both variable since they are the same */
11942  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11943  {
11944  --nactivevars;
11945  activevars[v] = activevars[nactivevars];
11946  }
11947  --v;
11948  }
11949  *requiredsize = nactivevars;
11950 
11951  if( varssize >= *requiredsize )
11952  {
11953  assert(vars != NULL);
11954 
11955  *nvars = *requiredsize;
11956  BMScopyMemoryArray(vars, activevars, nactivevars);
11957  }
11958 
11959  SCIPsetFreeBufferArray(set, &tmpvars);
11960  SCIPsetFreeBufferArray(set, &activevars);
11961 
11962  return SCIP_OKAY;
11963 }
11964 
11965 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11966  * @note the content of the given array will/might change
11967  */
11968 void SCIPvarsGetProbvar(
11969  SCIP_VAR** vars, /**< array of problem variables */
11970  int nvars /**< number of variables */
11971  )
11972 {
11973  int v;
11974 
11975  assert(vars != NULL || nvars == 0);
11976 
11977  for( v = nvars - 1; v >= 0; --v )
11978  {
11979  assert(vars != NULL);
11980  assert(vars[v] != NULL);
11981 
11982  vars[v] = SCIPvarGetProbvar(vars[v]);
11983  assert(vars[v] != NULL);
11984  }
11985 }
11986 
11987 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11989  SCIP_VAR* var /**< problem variable */
11990  )
11991 {
11992  SCIP_VAR* retvar;
11993 
11994  assert(var != NULL);
11995 
11996  retvar = var;
11997 
11998  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11999 
12000  while( TRUE ) /*lint !e716 */
12001  {
12002  assert(retvar != NULL);
12003 
12004  switch( SCIPvarGetStatus(retvar) )
12005  {
12007  if( retvar->data.original.transvar == NULL )
12008  {
12009  SCIPerrorMessage("original variable has no transformed variable attached\n");
12010  SCIPABORT();
12011  return NULL; /*lint !e527 */
12012  }
12013  retvar = retvar->data.original.transvar;
12014  break;
12015 
12016  case SCIP_VARSTATUS_LOOSE:
12017  case SCIP_VARSTATUS_COLUMN:
12018  case SCIP_VARSTATUS_FIXED:
12019  return retvar;
12020 
12022  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12023  if ( retvar->data.multaggr.nvars == 1 )
12024  retvar = retvar->data.multaggr.vars[0];
12025  else
12026  return retvar;
12027  break;
12028 
12030  retvar = retvar->data.aggregate.var;
12031  break;
12032 
12034  retvar = retvar->negatedvar;
12035  break;
12036 
12037  default:
12038  SCIPerrorMessage("unknown variable status\n");
12039  SCIPABORT();
12040  return NULL; /*lint !e527*/
12041  }
12042  }
12043 }
12044 
12045 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
12046  * negation status of each variable
12047  */
12049  SCIP_VAR*** vars, /**< pointer to binary problem variables */
12050  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
12051  int nvars /**< number of variables and values in vars and negated array */
12052  )
12053 {
12054  SCIP_VAR** var;
12055  SCIP_Bool* negated;
12056  int v;
12057 
12058  assert(vars != NULL);
12059  assert(*vars != NULL || nvars == 0);
12060  assert(negatedarr != NULL);
12061  assert(*negatedarr != NULL || nvars == 0);
12062 
12063  for( v = nvars - 1; v >= 0; --v )
12064  {
12065  var = &((*vars)[v]);
12066  negated = &((*negatedarr)[v]);
12067 
12068  /* get problem variable */
12069  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
12070  }
12071 
12072  return SCIP_OKAY;
12073 }
12074 
12075 
12076 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
12077  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
12078  * FALSE is used)
12079  */
12081  SCIP_VAR** var, /**< pointer to binary problem variable */
12082  SCIP_Bool* negated /**< pointer to update the negation status */
12083  )
12084 {
12086 #ifndef NDEBUG
12087  SCIP_Real constant = 0.0;
12088  SCIP_Bool orignegated;
12089 #endif
12090 
12091  assert(var != NULL);
12092  assert(*var != NULL);
12093  assert(negated != NULL);
12094  assert(SCIPvarIsBinary(*var));
12095 
12096 #ifndef NDEBUG
12097  orignegated = *negated;
12098 #endif
12099 
12100  while( !active && *var != NULL )
12101  {
12102  switch( SCIPvarGetStatus(*var) )
12103  {
12105  if( (*var)->data.original.transvar == NULL )
12106  return SCIP_OKAY;
12107  *var = (*var)->data.original.transvar;
12108  break;
12109 
12110  case SCIP_VARSTATUS_LOOSE:
12111  case SCIP_VARSTATUS_COLUMN:
12112  case SCIP_VARSTATUS_FIXED:
12113  active = TRUE;
12114  break;
12115 
12117  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12118  if ( (*var)->data.multaggr.nvars == 1 )
12119  {
12120  assert( (*var)->data.multaggr.vars != NULL );
12121  assert( (*var)->data.multaggr.scalars != NULL );
12122  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
12123  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
12124 
12125  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
12126  * another variable which needs to be fixed
12127  *
12128  * e.g. x = y - 1 => (x = 0 && y = 1)
12129  * e.g. x = y + 1 => (x = 1 && y = 0)
12130  *
12131  * is this special case we need to return the muti-aggregation
12132  */
12133  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)) )
12134  {
12135  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12136  }
12137  else
12138  {
12139  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
12140  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
12141  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
12142  * we will return the aggregated variable;
12143  */
12144  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
12145  {
12146  active = TRUE;
12147  break;
12148  }
12149 
12150  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
12151  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
12152  * so if this is the case, we will return the aggregated variable
12153  */
12154  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
12155  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
12156  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
12157 
12158  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
12159  {
12160  active = TRUE;
12161  break;
12162  }
12163 
12164  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12165 
12166  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
12167  {
12168  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
12169  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
12170  * variable itself is multi-aggregated again?
12171  */
12172  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
12173  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
12174  SCIPvarGetNLocksUpType((*var)->data.multaggr.vars[0], SCIP_LOCKTYPE_MODEL) > 0) : TRUE);
12175  }
12176  else
12177  {
12178  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
12179 #ifndef NDEBUG
12180  constant += (*negated) != orignegated ? -1.0 : 1.0;
12181 #endif
12182 
12183  *negated = !(*negated);
12184  }
12185  *var = (*var)->data.multaggr.vars[0];
12186  break;
12187  }
12188  }
12189  active = TRUE; /*lint !e838*/
12190  break;
12191 
12192  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12193  assert((*var)->data.aggregate.var != NULL);
12194  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
12195  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
12196 #ifndef NDEBUG
12197  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
12198 #endif
12199 
12200  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
12201  *var = (*var)->data.aggregate.var;
12202  break;
12203 
12204  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12205  assert((*var)->negatedvar != NULL);
12206 #ifndef NDEBUG
12207  constant += (*negated) != orignegated ? -1.0 : 1.0;
12208 #endif
12209 
12210  *negated = !(*negated);
12211  *var = (*var)->negatedvar;
12212  break;
12213 
12214  default:
12215  SCIPerrorMessage("unknown variable status\n");
12216  return SCIP_INVALIDDATA;
12217  }
12218  }
12219  assert(active == (*var != NULL));
12220 
12221  if( active )
12222  {
12223  assert(SCIPvarIsBinary(*var));
12224  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
12225  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
12226 
12227  return SCIP_OKAY;
12228  }
12229  else
12230  {
12231  SCIPerrorMessage("active variable path leads to NULL pointer\n");
12232  return SCIP_INVALIDDATA;
12233  }
12234 }
12235 
12236 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
12237  * values
12238  */
12240  SCIP_VAR** var, /**< pointer to problem variable */
12241  SCIP_Real* bound, /**< pointer to bound value to transform */
12242  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
12243  )
12244 {
12245  assert(var != NULL);
12246  assert(*var != NULL);
12247  assert(bound != NULL);
12248  assert(boundtype != NULL);
12249 
12250  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
12251 
12252  switch( SCIPvarGetStatus(*var) )
12253  {
12255  if( (*var)->data.original.transvar == NULL )
12256  {
12257  SCIPerrorMessage("original variable has no transformed variable attached\n");
12258  return SCIP_INVALIDDATA;
12259  }
12260  *var = (*var)->data.original.transvar;
12261  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12262  break;
12263 
12264  case SCIP_VARSTATUS_LOOSE:
12265  case SCIP_VARSTATUS_COLUMN:
12266  case SCIP_VARSTATUS_FIXED:
12267  break;
12268 
12270  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12271  if ( (*var)->data.multaggr.nvars == 1 )
12272  {
12273  assert( (*var)->data.multaggr.vars != NULL );
12274  assert( (*var)->data.multaggr.scalars != NULL );
12275  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
12276 
12277  (*bound) /= (*var)->data.multaggr.scalars[0];
12278  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
12279  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
12280  {
12281  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
12282  *boundtype = SCIP_BOUNDTYPE_UPPER;
12283  else
12284  *boundtype = SCIP_BOUNDTYPE_LOWER;
12285  }
12286  *var = (*var)->data.multaggr.vars[0];
12287  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12288  }
12289  break;
12290 
12291  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12292  assert((*var)->data.aggregate.var != NULL);
12293  assert((*var)->data.aggregate.scalar != 0.0);
12294 
12295  (*bound) /= (*var)->data.aggregate.scalar;
12296  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12297  if( (*var)->data.aggregate.scalar < 0.0 )
12298  {
12299  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12300  *boundtype = SCIP_BOUNDTYPE_UPPER;
12301  else
12302  *boundtype = SCIP_BOUNDTYPE_LOWER;
12303  }
12304  *var = (*var)->data.aggregate.var;
12305  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12306  break;
12307 
12308  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12309  assert((*var)->negatedvar != NULL);
12310  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12311  assert((*var)->negatedvar->negatedvar == *var);
12312  (*bound) = (*var)->data.negate.constant - *bound;
12313  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
12314  *boundtype = SCIP_BOUNDTYPE_UPPER;
12315  else
12316  *boundtype = SCIP_BOUNDTYPE_LOWER;
12317  *var = (*var)->negatedvar;
12318  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
12319  break;
12320 
12321  default:
12322  SCIPerrorMessage("unknown variable status\n");
12323  return SCIP_INVALIDDATA;
12324  }
12325 
12326  return SCIP_OKAY;
12327 }
12328 
12329 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
12330  * values
12331  */
12333  SCIP_VAR** var, /**< pointer to problem variable */
12334  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
12335  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
12336  )
12337 {
12338  assert(var != NULL);
12339  assert(*var != NULL);
12340  assert(left != NULL);
12341  assert(right != NULL);
12342 
12343  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
12344 
12345  switch( SCIPvarGetStatus(*var) )
12346  {
12348  if( (*var)->data.original.transvar == NULL )
12349  {
12350  SCIPerrorMessage("original variable has no transformed variable attached\n");
12351  return SCIP_INVALIDDATA;
12352  }
12353  *var = (*var)->data.original.transvar;
12354  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12355  break;
12356 
12357  case SCIP_VARSTATUS_LOOSE:
12358  case SCIP_VARSTATUS_COLUMN:
12359  case SCIP_VARSTATUS_FIXED:
12361  break;
12362 
12363  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12364  assert((*var)->data.aggregate.var != NULL);
12365  assert((*var)->data.aggregate.scalar != 0.0);
12366 
12367  /* scale back */
12368  (*left) /= (*var)->data.aggregate.scalar;
12369  (*right) /= (*var)->data.aggregate.scalar;
12370 
12371  /* shift back */
12372  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12373  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12374 
12375  *var = (*var)->data.aggregate.var;
12376 
12377  /* check if the interval bounds have to swapped */
12378  if( (*var)->data.aggregate.scalar < 0.0 )
12379  {
12380  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12381  }
12382  else
12383  {
12384  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12385  }
12386  break;
12387 
12388  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12389  assert((*var)->negatedvar != NULL);
12390  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12391  assert((*var)->negatedvar->negatedvar == *var);
12392 
12393  /* shift and scale back */
12394  (*left) = (*var)->data.negate.constant - (*left);
12395  (*right) = (*var)->data.negate.constant - (*right);
12396 
12397  *var = (*var)->negatedvar;
12398 
12399  /* through the negated variable the left and right interval bound have to swapped */
12400  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12401  break;
12402 
12403  default:
12404  SCIPerrorMessage("unknown variable status\n");
12405  return SCIP_INVALIDDATA;
12406  }
12407 
12408  return SCIP_OKAY;
12409 }
12410 
12411 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12412  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12413  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12414  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12415  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12416  */
12418  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12419  SCIP_SET* set, /**< global SCIP settings */
12420  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12421  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12422  )
12423 {
12424  assert(var != NULL);
12425  assert(scalar != NULL);
12426  assert(constant != NULL);
12427 
12428  while( *var != NULL )
12429  {
12430  switch( SCIPvarGetStatus(*var) )
12431  {
12433  if( (*var)->data.original.transvar == NULL )
12434  {
12435  SCIPerrorMessage("original variable has no transformed variable attached\n");
12436  return SCIP_INVALIDDATA;
12437  }
12438  *var = (*var)->data.original.transvar;
12439  break;
12440 
12441  case SCIP_VARSTATUS_LOOSE:
12442  case SCIP_VARSTATUS_COLUMN:
12443  return SCIP_OKAY;
12444 
12445  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12446  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12447  {
12448  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12449  {
12450  assert(*scalar != 0.0);
12451  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12452  (*constant) = SCIPsetInfinity(set);
12453  else
12454  (*constant) = -SCIPsetInfinity(set);
12455  }
12456  else
12457  (*constant) += *scalar * (*var)->glbdom.lb;
12458  }
12459 #ifndef NDEBUG
12460  else
12461  {
12462  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12463  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12464  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12465  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12466  }
12467 #endif
12468  *scalar = 0.0;
12469  return SCIP_OKAY;
12470 
12472  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12473  if ( (*var)->data.multaggr.nvars == 1 )
12474  {
12475  assert((*var)->data.multaggr.vars != NULL);
12476  assert((*var)->data.multaggr.scalars != NULL);
12477  assert((*var)->data.multaggr.vars[0] != NULL);
12478  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12479  {
12480  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12481  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12482  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12483  */
12484  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12485  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12486  {
12487  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12488  {
12489  assert(!SCIPsetIsInfinity(set, -(*constant)));
12490  (*constant) = SCIPsetInfinity(set);
12491  }
12492  else
12493  {
12494  assert(!SCIPsetIsInfinity(set, *constant));
12495  (*constant) = -SCIPsetInfinity(set);
12496  }
12497  (*scalar) = 0.0;
12498  }
12499  else
12500  (*constant) += *scalar * (*var)->data.multaggr.constant;
12501  }
12502  (*scalar) *= (*var)->data.multaggr.scalars[0];
12503  *var = (*var)->data.multaggr.vars[0];
12504  break;
12505  }
12506  return SCIP_OKAY;
12507 
12508  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12509  assert((*var)->data.aggregate.var != NULL);
12510  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12511  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12512  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12513  (*constant) += *scalar * (*var)->data.aggregate.constant;
12514  (*scalar) *= (*var)->data.aggregate.scalar;
12515  *var = (*var)->data.aggregate.var;
12516  break;
12517 
12518  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12519  assert((*var)->negatedvar != NULL);
12520  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12521  assert((*var)->negatedvar->negatedvar == *var);
12522  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12523  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12524  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12525  (*constant) += *scalar * (*var)->data.negate.constant;
12526  (*scalar) *= -1.0;
12527  *var = (*var)->negatedvar;
12528  break;
12529 
12530  default:
12531  SCIPerrorMessage("unknown variable status\n");
12532  SCIPABORT();
12533  return SCIP_INVALIDDATA; /*lint !e527*/
12534  }
12535  }
12536  *scalar = 0.0;
12537 
12538  return SCIP_OKAY;
12539 }
12540 
12541 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12542  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12543  */
12545  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12546  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12547  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12548  )
12549 {
12550  SCIP_VAR* parentvar;
12551 
12552  assert(var != NULL);
12553  assert(*var != NULL);
12554  assert(scalar != NULL);
12555  assert(constant != NULL);
12556 
12557  while( !SCIPvarIsOriginal(*var) )
12558  {
12559  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12560  * var
12561  */
12562  if( (*var)->nparentvars == 0 )
12563  {
12564  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12565  * space
12566  */
12568  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12569  {
12570  *scalar *= -1.0;
12571  *constant -= (*var)->data.negate.constant * (*scalar);
12572  *var = (*var)->negatedvar;
12573 
12574  continue;
12575  }
12576  /* if the variables does not have any parent the variables was created during solving and has no original
12577  * counterpart
12578  */
12579  else
12580  {
12581  *var = NULL;
12582 
12583  return SCIP_OKAY;
12584  }
12585  }
12586 
12587  /* follow the link to the first parent variable */
12588  parentvar = (*var)->parentvars[0];
12589  assert(parentvar != NULL);
12590 
12591  switch( SCIPvarGetStatus(parentvar) )
12592  {
12594  break;
12595 
12596  case SCIP_VARSTATUS_COLUMN:
12597  case SCIP_VARSTATUS_LOOSE:
12598  case SCIP_VARSTATUS_FIXED:
12600  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12601  return SCIP_INVALIDDATA;
12602 
12603  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12604  assert(parentvar->data.aggregate.var == *var);
12605  assert(parentvar->data.aggregate.scalar != 0.0);
12606  *scalar /= parentvar->data.aggregate.scalar;
12607  *constant -= parentvar->data.aggregate.constant * (*scalar);
12608  break;
12609 
12610  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12611  assert(parentvar->negatedvar != NULL);
12612  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12613  assert(parentvar->negatedvar->negatedvar == parentvar);
12614  *scalar *= -1.0;
12615  *constant -= parentvar->data.negate.constant * (*scalar);
12616  break;
12617 
12618  default:
12619  SCIPerrorMessage("unknown variable status\n");
12620  return SCIP_INVALIDDATA;
12621  }
12622 
12623  assert( parentvar != NULL );
12624  *var = parentvar;
12625  }
12626 
12627  return SCIP_OKAY;
12628 }
12629 
12630 /** returns whether the given variable is the direct counterpart of an original problem variable */
12632  SCIP_VAR* var /**< problem variable */
12633  )
12634 {
12635  SCIP_VAR* parentvar;
12636  assert(var != NULL);
12637 
12638  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12639  return FALSE;
12640 
12641  assert(var->parentvars != NULL);
12642  parentvar = var->parentvars[0];
12643  assert(parentvar != NULL);
12644 
12645  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12646  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12647  parentvar = parentvar->parentvars[0];
12648  assert( parentvar != NULL );
12649 
12650  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12651 }
12652 
12653 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12654  * the variable's own data due to diving, that operate only on the LP without updating the variables
12655  */
12657  SCIP_VAR* var /**< problem variable */
12658  )
12659 {
12660  assert(var != NULL);
12661 
12662  /* get bounds of attached variables */
12663  switch( SCIPvarGetStatus(var) )
12664  {
12666  assert(var->data.original.transvar != NULL);
12667  return SCIPvarGetObjLP(var->data.original.transvar);
12668 
12669  case SCIP_VARSTATUS_COLUMN:
12670  assert(var->data.col != NULL);
12671  return SCIPcolGetObj(var->data.col);
12672 
12673  case SCIP_VARSTATUS_LOOSE:
12674  case SCIP_VARSTATUS_FIXED:
12675  return var->obj;
12676 
12677  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12678  assert(var->data.aggregate.var != NULL);
12679  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12680 
12682  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12683  SCIPABORT();
12684  return 0.0; /*lint !e527*/
12685 
12686  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12687  assert(var->negatedvar != NULL);
12689  assert(var->negatedvar->negatedvar == var);
12690  return -SCIPvarGetObjLP(var->negatedvar);
12691 
12692  default:
12693  SCIPerrorMessage("unknown variable status\n");
12694  SCIPABORT();
12695  return 0.0; /*lint !e527*/
12696  }
12697 }
12698 
12699 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12700  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12701  */
12703  SCIP_VAR* var, /**< problem variable */
12704  SCIP_SET* set /**< global SCIP settings */
12705  )
12706 {
12707  assert(var != NULL);
12708  assert(set != NULL);
12709  assert(var->scip == set->scip);
12710 
12711  /* get bounds of attached variables */
12712  switch( SCIPvarGetStatus(var) )
12713  {
12715  assert(var->data.original.transvar != NULL);
12716  return SCIPvarGetLbLP(var->data.original.transvar, set);
12717 
12718  case SCIP_VARSTATUS_COLUMN:
12719  assert(var->data.col != NULL);
12720  return SCIPcolGetLb(var->data.col);
12721 
12722  case SCIP_VARSTATUS_LOOSE:
12723  case SCIP_VARSTATUS_FIXED:
12724  return var->locdom.lb;
12725 
12726  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12727  assert(var->data.aggregate.var != NULL);
12728  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12729  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12730  {
12731  return -SCIPsetInfinity(set);
12732  }
12733  else if( var->data.aggregate.scalar > 0.0 )
12734  {
12735  /* a > 0 -> get lower bound of y */
12736  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12737  }
12738  else if( var->data.aggregate.scalar < 0.0 )
12739  {
12740  /* a < 0 -> get upper bound of y */
12741  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12742  }
12743  else
12744  {
12745  SCIPerrorMessage("scalar is zero in aggregation\n");
12746  SCIPABORT();
12747  return SCIP_INVALID; /*lint !e527*/
12748  }
12749 
12751  /**@todo get the sides of the corresponding linear constraint */
12752  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12753  SCIPABORT();
12754  return SCIP_INVALID; /*lint !e527*/
12755 
12756  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12757  assert(var->negatedvar != NULL);
12759  assert(var->negatedvar->negatedvar == var);
12760  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12761 
12762  default:
12763  SCIPerrorMessage("unknown variable status\n");
12764  SCIPABORT();
12765  return SCIP_INVALID; /*lint !e527*/
12766  }
12767 }
12768 
12769 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12770  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12771  */
12773  SCIP_VAR* var, /**< problem variable */
12774  SCIP_SET* set /**< global SCIP settings */
12775  )
12776 {
12777  assert(var != NULL);
12778  assert(set != NULL);
12779  assert(var->scip == set->scip);
12780 
12781  /* get bounds of attached variables */
12782  switch( SCIPvarGetStatus(var) )
12783  {
12785  assert(var->data.original.transvar != NULL);
12786  return SCIPvarGetUbLP(var->data.original.transvar, set);
12787 
12788  case SCIP_VARSTATUS_COLUMN:
12789  assert(var->data.col != NULL);
12790  return SCIPcolGetUb(var->data.col);
12791 
12792  case SCIP_VARSTATUS_LOOSE:
12793  case SCIP_VARSTATUS_FIXED:
12794  return var->locdom.ub;
12795 
12796  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12797  assert(var->data.aggregate.var != NULL);
12798  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12799  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12800  {
12801  return SCIPsetInfinity(set);
12802  }
12803  if( var->data.aggregate.scalar > 0.0 )
12804  {
12805  /* a > 0 -> get upper bound of y */
12806  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12807  }
12808  else if( var->data.aggregate.scalar < 0.0 )
12809  {
12810  /* a < 0 -> get lower bound of y */
12811  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12812  }
12813  else
12814  {
12815  SCIPerrorMessage("scalar is zero in aggregation\n");
12816  SCIPABORT();
12817  return SCIP_INVALID; /*lint !e527*/
12818  }
12819 
12821  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12822  SCIPABORT();
12823  return SCIP_INVALID; /*lint !e527*/
12824 
12825  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12826  assert(var->negatedvar != NULL);
12828  assert(var->negatedvar->negatedvar == var);
12829  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12830 
12831  default:
12832  SCIPerrorMessage("unknown variable status\n");
12833  SCIPABORT();
12834  return SCIP_INVALID; /*lint !e527*/
12835  }
12836 }
12837 
12838 /** gets primal LP solution value of variable */
12840  SCIP_VAR* var /**< problem variable */
12841  )
12842 {
12843  assert(var != NULL);
12844 
12845  switch( SCIPvarGetStatus(var) )
12846  {
12848  if( var->data.original.transvar == NULL )
12849  return SCIP_INVALID;
12850  return SCIPvarGetLPSol(var->data.original.transvar);
12851 
12852  case SCIP_VARSTATUS_LOOSE:
12853  return SCIPvarGetBestBoundLocal(var);
12854 
12855  case SCIP_VARSTATUS_COLUMN:
12856  assert(var->data.col != NULL);
12857  return SCIPcolGetPrimsol(var->data.col);
12858 
12859  case SCIP_VARSTATUS_FIXED:
12860  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12861  return var->locdom.lb;
12862 
12864  {
12865  SCIP_Real lpsolval;
12866 
12867  assert(var->data.aggregate.var != NULL);
12868  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12869 
12870  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12871  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12872  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12873  * (or is called by) a public interface method; instead, we only assert that values are finite
12874  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12875  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12876  */
12877  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12878  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12879  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12880  }
12882  {
12883  SCIP_Real primsol;
12884  int i;
12885 
12886  assert(!var->donotmultaggr);
12887  assert(var->data.multaggr.vars != NULL);
12888  assert(var->data.multaggr.scalars != NULL);
12889  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12890  * assert(var->data.multaggr.nvars >= 2);
12891  */
12892  primsol = var->data.multaggr.constant;
12893  for( i = 0; i < var->data.multaggr.nvars; ++i )
12894  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12895  return primsol;
12896  }
12897  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12898  assert(var->negatedvar != NULL);
12900  assert(var->negatedvar->negatedvar == var);
12901  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12902 
12903  default:
12904  SCIPerrorMessage("unknown variable status\n");
12905  SCIPABORT();
12906  return SCIP_INVALID; /*lint !e527*/
12907  }
12908 }
12909 
12910 /** gets primal NLP solution value of variable */
12912  SCIP_VAR* var /**< problem variable */
12913  )
12914 {
12915  SCIP_Real solval;
12916  int i;
12917 
12918  assert(var != NULL);
12919 
12920  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12921  switch( SCIPvarGetStatus(var) )
12922  {
12924  return SCIPvarGetNLPSol(var->data.original.transvar);
12925 
12926  case SCIP_VARSTATUS_LOOSE:
12927  case SCIP_VARSTATUS_COLUMN:
12928  return var->nlpsol;
12929 
12930  case SCIP_VARSTATUS_FIXED:
12931  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12932  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12933  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12934  return SCIPvarGetLbGlobal(var);
12935 
12936  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12937  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12938  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12939 
12941  solval = var->data.multaggr.constant;
12942  for( i = 0; i < var->data.multaggr.nvars; ++i )
12943  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12944  return solval;
12945 
12947  solval = SCIPvarGetNLPSol(var->negatedvar);
12948  return var->data.negate.constant - solval;
12949 
12950  default:
12951  SCIPerrorMessage("unknown variable status\n");
12952  SCIPABORT();
12953  return SCIP_INVALID; /*lint !e527*/
12954  }
12955 }
12956 
12957 /** gets pseudo solution value of variable at current node */
12958 static
12960  SCIP_VAR* var /**< problem variable */
12961  )
12962 {
12963  SCIP_Real pseudosol;
12964  int i;
12965 
12966  assert(var != NULL);
12967 
12968  switch( SCIPvarGetStatus(var) )
12969  {
12971  if( var->data.original.transvar == NULL )
12972  return SCIP_INVALID;
12974 
12975  case SCIP_VARSTATUS_LOOSE:
12976  case SCIP_VARSTATUS_COLUMN:
12977  return SCIPvarGetBestBoundLocal(var);
12978 
12979  case SCIP_VARSTATUS_FIXED:
12980  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12981  return var->locdom.lb;
12982 
12984  {
12985  SCIP_Real pseudosolval;
12986  assert(var->data.aggregate.var != NULL);
12987  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12988  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12989  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12990  * (or is called by) a public interface method; instead, we only assert that values are finite
12991  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12992  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12993  */
12994  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12995  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12996  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12997  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12998  }
13000  assert(!var->donotmultaggr);
13001  assert(var->data.multaggr.vars != NULL);
13002  assert(var->data.multaggr.scalars != NULL);
13003  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13004  * assert(var->data.multaggr.nvars >= 2);
13005  */
13006  pseudosol = var->data.multaggr.constant;
13007  for( i = 0; i < var->data.multaggr.nvars; ++i )
13008  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
13009  return pseudosol;
13010 
13011  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13012  assert(var->negatedvar != NULL);
13014  assert(var->negatedvar->negatedvar == var);
13015  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
13016 
13017  default:
13018  SCIPerrorMessage("unknown variable status\n");
13019  SCIPABORT();
13020  return SCIP_INVALID; /*lint !e527*/
13021  }
13022 }
13023 
13024 /** gets current LP or pseudo solution value of variable */
13026  SCIP_VAR* var, /**< problem variable */
13027  SCIP_Bool getlpval /**< should the LP solution value be returned? */
13028  )
13029 {
13030  if( getlpval )
13031  return SCIPvarGetLPSol(var);
13032  else
13033  return SCIPvarGetPseudoSol(var);
13034 }
13035 
13036 /** remembers the current solution as root solution in the problem variables */
13037 void SCIPvarStoreRootSol(
13038  SCIP_VAR* var, /**< problem variable */
13039  SCIP_Bool roothaslp /**< is the root solution from LP? */
13040  )
13041 {
13042  assert(var != NULL);
13043 
13044  var->rootsol = SCIPvarGetSol(var, roothaslp);
13045 }
13046 
13047 /** updates the current solution as best root solution of the given variable if it is better */
13049  SCIP_VAR* var, /**< problem variable */
13050  SCIP_SET* set, /**< global SCIP settings */
13051  SCIP_Real rootsol, /**< root solution value */
13052  SCIP_Real rootredcost, /**< root reduced cost */
13053  SCIP_Real rootlpobjval /**< objective value of the root LP */
13054  )
13055 {
13056  assert(var != NULL);
13057  assert(set != NULL);
13058  assert(var->scip == set->scip);
13059 
13060  /* if reduced cost are zero nothing to update */
13061  if( SCIPsetIsDualfeasZero(set, rootredcost) )
13062  return;
13063 
13064  /* check if we have already a best combination stored */
13065  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
13066  {
13067  SCIP_Real currcutoffbound;
13068  SCIP_Real cutoffbound;
13069  SCIP_Real bound;
13070 
13071  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
13072  * root reduced cost, and root LP objective value combination
13073  */
13074  if( var->bestrootredcost > 0.0 )
13075  bound = SCIPvarGetUbGlobal(var);
13076  else
13077  bound = SCIPvarGetLbGlobal(var);
13078 
13079  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
13080 
13081  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
13082  * cost, and root LP objective value combination
13083  */
13084  if( rootredcost > 0.0 )
13085  bound = SCIPvarGetUbGlobal(var);
13086  else
13087  bound = SCIPvarGetLbGlobal(var);
13088 
13089  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
13090 
13091  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
13092  if( cutoffbound > currcutoffbound )
13093  {
13094  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
13095  SCIPvarGetName(var), currcutoffbound, cutoffbound);
13096 
13097  var->bestrootsol = rootsol;
13098  var->bestrootredcost = rootredcost;
13099  var->bestrootlpobjval = rootlpobjval;
13100  }
13101  }
13102  else
13103  {
13104  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
13105  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
13106  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
13107  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
13108 
13109  var->bestrootsol = rootsol;
13110  var->bestrootredcost = rootredcost;
13111  var->bestrootlpobjval = rootlpobjval;
13112  }
13113 }
13114 
13115 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
13116  * completely solved, zero is returned
13117  */
13119  SCIP_VAR* var /**< problem variable */
13120  )
13121 {
13122  SCIP_Real rootsol;
13123  int i;
13124 
13125  assert(var != NULL);
13126 
13127  switch( SCIPvarGetStatus(var) )
13128  {
13130  if( var->data.original.transvar == NULL )
13131  return 0.0;
13132  return SCIPvarGetRootSol(var->data.original.transvar);
13133 
13134  case SCIP_VARSTATUS_LOOSE:
13135  case SCIP_VARSTATUS_COLUMN:
13136  return var->rootsol;
13137 
13138  case SCIP_VARSTATUS_FIXED:
13139  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13140  return var->locdom.lb;
13141 
13143  assert(var->data.aggregate.var != NULL);
13144  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13145  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13146  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13147  * (or is called by) a public interface method; instead, we only assert that values are finite
13148  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13149  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13150  */
13154 
13156  assert(!var->donotmultaggr);
13157  assert(var->data.multaggr.vars != NULL);
13158  assert(var->data.multaggr.scalars != NULL);
13159  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13160  * assert(var->data.multaggr.nvars >= 2);
13161  */
13162  rootsol = var->data.multaggr.constant;
13163  for( i = 0; i < var->data.multaggr.nvars; ++i )
13164  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
13165  return rootsol;
13166 
13167  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13168  assert(var->negatedvar != NULL);
13170  assert(var->negatedvar->negatedvar == var);
13171  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
13172 
13173  default:
13174  SCIPerrorMessage("unknown variable status\n");
13175  SCIPABORT();
13176  return SCIP_INVALID; /*lint !e527*/
13177  }
13178 }
13179 
13180 /** returns for given variable the reduced cost */
13181 static
13183  SCIP_VAR* var, /**< problem variable */
13184  SCIP_SET* set, /**< global SCIP settings */
13185  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13186  SCIP_STAT* stat, /**< problem statistics */
13187  SCIP_LP* lp /**< current LP data */
13188  )
13189 {
13191  {
13192  SCIP_COL* col;
13193  SCIP_Real primsol;
13194  SCIP_BASESTAT basestat;
13195  SCIP_Bool lpissolbasic;
13196 
13197  col = SCIPvarGetCol(var);
13198  assert(col != NULL);
13199 
13200  basestat = SCIPcolGetBasisStatus(col);
13201  lpissolbasic = SCIPlpIsSolBasic(lp);
13202  primsol = SCIPcolGetPrimsol(col);
13203 
13204  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
13205  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
13206  {
13207  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
13208 
13209  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
13210  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
13212  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
13213  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
13214  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
13215 
13216  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
13217  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
13218  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
13219  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
13220  return redcost;
13221  else
13222  return 0.0;
13223  }
13224 
13225  return 0.0;
13226  }
13227 
13228  return 0.0;
13229 }
13230 
13231 #define MAX_CLIQUELENGTH 50
13232 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
13233  * the binary variable is fixed to the given value
13234  */
13236  SCIP_VAR* var, /**< problem variable */
13237  SCIP_SET* set, /**< global SCIP settings */
13238  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
13239  SCIP_STAT* stat, /**< problem statistics */
13240  SCIP_PROB* prob, /**< transformed problem, or NULL */
13241  SCIP_LP* lp /**< current LP data */
13242  )
13243 {
13244  SCIP_Real implredcost;
13245  int ncliques;
13246  int nvars;
13247 
13248  assert(SCIPvarIsBinary(var));
13249  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13250 
13251  /* get reduced cost of given variable */
13252  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
13253 
13254 #ifdef SCIP_MORE_DEBUG
13255  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
13256 #endif
13257 
13258  /* the following algorithm is expensive */
13259  ncliques = SCIPvarGetNCliques(var, varfixing);
13260 
13261  if( ncliques > 0 )
13262  {
13263  SCIP_CLIQUE** cliques;
13264  SCIP_CLIQUE* clique;
13265  SCIP_VAR** clqvars;
13266  SCIP_VAR** probvars;
13267  SCIP_VAR* clqvar;
13268  SCIP_Bool* clqvalues;
13269  int* entries;
13270  int* ids;
13271  SCIP_Real redcost;
13272  SCIP_Bool cleanedup;
13273  int nclqvars;
13274  int nentries;
13275  int nids;
13276  int id;
13277  int c;
13278  int v;
13279 
13280  assert(prob != NULL);
13281  assert(SCIPprobIsTransformed(prob));
13282 
13283  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
13284 
13285  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
13286  nids = 0;
13287  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
13288 
13289  cliques = SCIPvarGetCliques(var, varfixing);
13290  assert(cliques != NULL);
13291 
13292  for( c = ncliques - 1; c >= 0; --c )
13293  {
13294  clique = cliques[c];
13295  assert(clique != NULL);
13296  nclqvars = SCIPcliqueGetNVars(clique);
13297  assert(nclqvars > 0);
13298 
13299  if( nclqvars > MAX_CLIQUELENGTH )
13300  continue;
13301 
13302  clqvars = SCIPcliqueGetVars(clique);
13303  clqvalues = SCIPcliqueGetValues(clique);
13304  assert(clqvars != NULL);
13305  assert(clqvalues != NULL);
13306 
13307  cleanedup = SCIPcliqueIsCleanedUp(clique);
13308 
13309  for( v = nclqvars - 1; v >= 0; --v )
13310  {
13311  clqvar = clqvars[v];
13312  assert(clqvar != NULL);
13313 
13314  /* ignore binary variable which are fixed */
13315  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
13316  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
13317  {
13318  int probindex = SCIPvarGetProbindex(clqvar) + 1;
13319  assert(0 < probindex && probindex < nentries);
13320 
13321 #if 0
13322  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
13323  * can appear since there is no guarantee that all these infeasible bounds were found
13324  */
13325  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
13326 #endif
13327  if( entries[probindex] == 0 )
13328  {
13329  ids[nids] = probindex;
13330  ++nids;
13331 
13332  /* mark variable as visited */
13333  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
13334  }
13335  }
13336  }
13337  }
13338 
13339  probvars = SCIPprobGetVars(prob);
13340  assert(probvars != NULL);
13341 
13342  /* add all implied reduced cost */
13343  for( v = nids - 1; v >= 0; --v )
13344  {
13345  id = ids[v];
13346  assert(0 < id && id < nentries);
13347  assert(entries[id] != 0);
13348  assert(probvars[id - 1] != NULL);
13349  assert(SCIPvarIsActive(probvars[id - 1]));
13350  assert(SCIPvarIsBinary(probvars[id - 1]));
13351  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
13352 
13353  if( (entries[id] > 0) != varfixing )
13354  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13355  else
13356  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
13357 
13358  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13359  implredcost += redcost;
13360 
13361  /* reset entries clear buffer array */
13362  entries[id] = 0;
13363  }
13364 
13365  SCIPsetFreeCleanBufferArray(set, &entries);
13366  SCIPsetFreeBufferArray(set, &ids);
13367  }
13368 
13369 #ifdef SCIP_MORE_DEBUG
13370  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13371  implredcost);
13372 #endif
13373 
13374  /* collect non-binary implication information */
13375  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13376 
13377  if( nvars > 0 )
13378  {
13379  SCIP_VAR** vars;
13380  SCIP_VAR* implvar;
13381  SCIP_COL* col;
13382  SCIP_Real* bounds;
13383  SCIP_BOUNDTYPE* boundtypes;
13384  SCIP_Real redcost;
13385  SCIP_Real lb;
13386  SCIP_Real ub;
13387  SCIP_Bool lpissolbasic;
13388  int v;
13389 
13390  vars = SCIPimplicsGetVars(var->implics, varfixing);
13391  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13392  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13393  lpissolbasic = SCIPlpIsSolBasic(lp);
13394 
13395  for( v = nvars - 1; v >= 0; --v )
13396  {
13397  implvar = vars[v];
13398  assert(implvar != NULL);
13399 
13400  lb = SCIPvarGetLbLocal(implvar);
13401  ub = SCIPvarGetUbLocal(implvar);
13402 
13403  /* ignore binary variable which are fixed or not of column status */
13404  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13405  continue;
13406 
13407  col = SCIPvarGetCol(implvar);
13408  assert(col != NULL);
13409  redcost = 0.0;
13410 
13411  /* solved lp with basis information or not? */
13412  if( lpissolbasic )
13413  {
13414  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13415 
13416  /* check if the implication is not not yet applied */
13417  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13418  {
13419  redcost = SCIPcolGetRedcost(col, stat, lp);
13420  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13421 
13422  if( !varfixing )
13423  redcost *= (lb - bounds[v]);
13424  else
13425  redcost *= (bounds[v] - lb);
13426  }
13427  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13428  {
13429  redcost = SCIPcolGetRedcost(col, stat, lp);
13430  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13431 
13432  if( varfixing )
13433  redcost *= (bounds[v] - ub);
13434  else
13435  redcost *= (ub - bounds[v]);
13436  }
13437  }
13438  else
13439  {
13440  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13441 
13442  /* check if the implication is not not yet applied */
13443  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13444  {
13445  redcost = SCIPcolGetRedcost(col, stat, lp);
13446  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13447 
13448  if( varfixing )
13449  redcost *= (lb - bounds[v]);
13450  else
13451  redcost *= (bounds[v] - lb);
13452  }
13453  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13454  {
13455  redcost = SCIPcolGetRedcost(col, stat, lp);
13456  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13457 
13458  if( varfixing )
13459  redcost *= (bounds[v] - ub);
13460  else
13461  redcost *= (ub - bounds[v]);
13462  }
13463  }
13464 
13465  /* improve implied reduced cost */
13466  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13467  implredcost += redcost;
13468  }
13469  }
13470 
13471 #ifdef SCIP_MORE_DEBUG
13472  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13473  SCIPvarGetName(var), ncliques, nvars, implredcost);
13474 #endif
13475 
13476  return implredcost;
13477 }
13478 
13479 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13480  * the root relaxation is not yet completely solved, zero is returned
13481  */
13483  SCIP_VAR* var /**< problem variable */
13484  )
13485 {
13486  SCIP_Real rootsol;
13487  int i;
13488 
13489  assert(var != NULL);
13490 
13491  switch( SCIPvarGetStatus(var) )
13492  {
13494  if( var->data.original.transvar == NULL )
13495  return 0.0;
13497 
13498  case SCIP_VARSTATUS_LOOSE:
13499  case SCIP_VARSTATUS_COLUMN:
13500  return var->bestrootsol;
13501 
13502  case SCIP_VARSTATUS_FIXED:
13503  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13504  return var->locdom.lb;
13505 
13507  assert(var->data.aggregate.var != NULL);
13508  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13509  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13510  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13511  * (or is called by) a public interface method; instead, we only assert that values are finite
13512  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13513  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13514  */
13518 
13520  assert(!var->donotmultaggr);
13521  assert(var->data.multaggr.vars != NULL);
13522  assert(var->data.multaggr.scalars != NULL);
13523  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13524  * assert(var->data.multaggr.nvars >= 2);
13525  */
13526  rootsol = var->data.multaggr.constant;
13527  for( i = 0; i < var->data.multaggr.nvars; ++i )
13528  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13529  return rootsol;
13530 
13531  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13532  assert(var->negatedvar != NULL);
13534  assert(var->negatedvar->negatedvar == var);
13535  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13536 
13537  default:
13538  SCIPerrorMessage("unknown variable status\n");
13539  SCIPABORT();
13540  return 0.0; /*lint !e527*/
13541  }
13542 }
13543 
13544 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13545  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13546  * returned
13547  */
13549  SCIP_VAR* var /**< problem variable */
13550  )
13551 {
13552  assert(var != NULL);
13553 
13554  switch( SCIPvarGetStatus(var) )
13555  {
13557  if( var->data.original.transvar == NULL )
13558  return SCIP_INVALID;
13560 
13561  case SCIP_VARSTATUS_LOOSE:
13562  case SCIP_VARSTATUS_COLUMN:
13563  return var->bestrootredcost;
13564 
13565  case SCIP_VARSTATUS_FIXED:
13569  return 0.0;
13570 
13571  default:
13572  SCIPerrorMessage("unknown variable status\n");
13573  SCIPABORT();
13574  return 0.0; /*lint !e527*/
13575  }
13576 }
13577 
13578 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13579  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13580  * SCIP_INVALID is returned
13581  */
13583  SCIP_VAR* var /**< problem variable */
13584  )
13585 {
13586  assert(var != NULL);
13587 
13588  switch( SCIPvarGetStatus(var) )
13589  {
13591  if( var->data.original.transvar == NULL )
13592  return SCIP_INVALID;
13594 
13595  case SCIP_VARSTATUS_LOOSE:
13596  case SCIP_VARSTATUS_COLUMN:
13597  return var->bestrootlpobjval;
13598 
13599  case SCIP_VARSTATUS_FIXED:
13603  return SCIP_INVALID;
13604 
13605  default:
13606  SCIPerrorMessage("unknown variable status\n");
13607  SCIPABORT();
13608  return SCIP_INVALID; /*lint !e527*/
13609  }
13610 }
13611 
13612 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13614  SCIP_VAR* var, /**< problem variable */
13615  SCIP_Real rootsol, /**< root solution value */
13616  SCIP_Real rootredcost, /**< root reduced cost */
13617  SCIP_Real rootlpobjval /**< objective value of the root LP */
13618  )
13619 {
13620  assert(var != NULL);
13621 
13622  var->bestrootsol = rootsol;
13623  var->bestrootredcost = rootredcost;
13624  var->bestrootlpobjval = rootlpobjval;
13625 }
13626 
13627 /** stores the solution value as relaxation solution in the problem variable */
13629  SCIP_VAR* var, /**< problem variable */
13630  SCIP_SET* set, /**< global SCIP settings */
13631  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13632  SCIP_Real solval, /**< solution value in the current relaxation solution */
13633  SCIP_Bool updateobj /**< should the objective value be updated? */
13634  )
13635 {
13636  assert(var != NULL);
13637  assert(relaxation != NULL);
13638  assert(set != NULL);
13639  assert(var->scip == set->scip);
13640 
13641  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13642  switch( SCIPvarGetStatus(var) )
13643  {
13645  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13646  break;
13647 
13648  case SCIP_VARSTATUS_LOOSE:
13649  case SCIP_VARSTATUS_COLUMN:
13650  if( updateobj )
13651  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13652  var->relaxsol = solval;
13653  break;
13654 
13655  case SCIP_VARSTATUS_FIXED:
13656  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13657  {
13658  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13659  SCIPvarGetName(var), var->glbdom.lb, solval);
13660  return SCIP_INVALIDDATA;
13661  }
13662  break;
13663 
13664  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13665  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13666  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13667  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13668  break;
13670  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13671  return SCIP_INVALIDDATA;
13672 
13674  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13675  break;
13676 
13677  default:
13678  SCIPerrorMessage("unknown variable status\n");
13679  return SCIP_INVALIDDATA;
13680  }
13681 
13682  return SCIP_OKAY;
13683 }
13684 
13685 /** returns the solution value of the problem variable in the relaxation solution
13686  *
13687  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13688  */
13690  SCIP_VAR* var, /**< problem variable */
13691  SCIP_SET* set /**< global SCIP settings */
13692  )
13693 {
13694  SCIP_Real solvalsum;
13695  SCIP_Real solval;
13696  int i;
13697 
13698  assert(var != NULL);
13699  assert(set != NULL);
13700  assert(var->scip == set->scip);
13701 
13702  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13703  switch( SCIPvarGetStatus(var) )
13704  {
13706  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13707 
13708  case SCIP_VARSTATUS_LOOSE:
13709  case SCIP_VARSTATUS_COLUMN:
13710  return var->relaxsol;
13711 
13712  case SCIP_VARSTATUS_FIXED:
13713  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13714  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13715  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13716  return SCIPvarGetLbGlobal(var);
13717 
13718  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13719  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13720  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13721  {
13722  if( var->data.aggregate.scalar * solval > 0.0 )
13723  return SCIPsetInfinity(set);
13724  if( var->data.aggregate.scalar * solval < 0.0 )
13725  return -SCIPsetInfinity(set);
13726  }
13727  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13728 
13730  solvalsum = var->data.multaggr.constant;
13731  for( i = 0; i < var->data.multaggr.nvars; ++i )
13732  {
13733  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13734  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13735  {
13736  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13737  return SCIPsetInfinity(set);
13738  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13739  return -SCIPsetInfinity(set);
13740  }
13741  solvalsum += var->data.multaggr.scalars[i] * solval;
13742  }
13743  return solvalsum;
13744 
13746  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13747  if( SCIPsetIsInfinity(set, solval) )
13748  return -SCIPsetInfinity(set);
13749  if( SCIPsetIsInfinity(set, -solval) )
13750  return SCIPsetInfinity(set);
13751  return var->data.negate.constant - solval;
13752 
13753  default:
13754  SCIPerrorMessage("unknown variable status\n");
13755  SCIPABORT();
13756  return SCIP_INVALID; /*lint !e527*/
13757  }
13758 }
13759 
13760 /** returns the solution value of the transformed problem variable in the relaxation solution */
13762  SCIP_VAR* var /**< problem variable */
13763  )
13764 {
13765  assert(var != NULL);
13767 
13768  return var->relaxsol;
13769 }
13770 
13771 /** stores the solution value as NLP solution in the problem variable */
13773  SCIP_VAR* var, /**< problem variable */
13774  SCIP_SET* set, /**< global SCIP settings */
13775  SCIP_Real solval /**< solution value in the current NLP solution */
13776  )
13777 {
13778  assert(var != NULL);
13779  assert(set != NULL);
13780  assert(var->scip == set->scip);
13781 
13782  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13783  switch( SCIPvarGetStatus(var) )
13784  {
13786  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13787  break;
13788 
13789  case SCIP_VARSTATUS_LOOSE:
13790  case SCIP_VARSTATUS_COLUMN:
13791  var->nlpsol = solval;
13792  break;
13793 
13794  case SCIP_VARSTATUS_FIXED:
13795  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13796  {
13797  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13798  SCIPvarGetName(var), var->glbdom.lb, solval);
13799  SCIPABORT();
13800  return SCIP_INVALIDCALL; /*lint !e527*/
13801  }
13802  break;
13803 
13804  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13805  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13806  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13807  break;
13808 
13810  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13811  SCIPABORT();
13812  return SCIP_INVALIDCALL; /*lint !e527*/
13813 
13815  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13816  break;
13817 
13818  default:
13819  SCIPerrorMessage("unknown variable status\n");
13820  SCIPABORT();
13821  return SCIP_ERROR; /*lint !e527*/
13822  }
13823 
13824  return SCIP_OKAY;
13825 }
13826 
13827 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13829  SCIP_VAR* var /**< problem variable */
13830  )
13831 {
13832  SCIP_Real avgsol;
13833  int i;
13834 
13835  assert(var != NULL);
13836 
13837  switch( SCIPvarGetStatus(var) )
13838  {
13840  if( var->data.original.transvar == NULL )
13841  return 0.0;
13842  return SCIPvarGetAvgSol(var->data.original.transvar);
13843 
13844  case SCIP_VARSTATUS_LOOSE:
13845  case SCIP_VARSTATUS_COLUMN:
13846  avgsol = var->primsolavg;
13847  avgsol = MAX(avgsol, var->glbdom.lb);
13848  avgsol = MIN(avgsol, var->glbdom.ub);
13849  return avgsol;
13850 
13851  case SCIP_VARSTATUS_FIXED:
13852  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13853  return var->locdom.lb;
13854 
13856  assert(var->data.aggregate.var != NULL);
13857  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13858  + var->data.aggregate.constant;
13859 
13861  assert(!var->donotmultaggr);
13862  assert(var->data.multaggr.vars != NULL);
13863  assert(var->data.multaggr.scalars != NULL);
13864  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13865  * assert(var->data.multaggr.nvars >= 2);
13866  */
13867  avgsol = var->data.multaggr.constant;
13868  for( i = 0; i < var->data.multaggr.nvars; ++i )
13869  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13870  return avgsol;
13871 
13872  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13873  assert(var->negatedvar != NULL);
13875  assert(var->negatedvar->negatedvar == var);
13876  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13877 
13878  default:
13879  SCIPerrorMessage("unknown variable status\n");
13880  SCIPABORT();
13881  return 0.0; /*lint !e527*/
13882  }
13883 }
13884 
13885 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13886  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13887  */
13889  SCIP_VAR* var, /**< active problem variable */
13890  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13891  SCIP_SET* set, /**< global SCIP settings */
13892  SCIP_STAT* stat, /**< problem statistics */
13893  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13894  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13895  )
13896 {
13897  int nvlbs;
13898 
13899  assert(var != NULL);
13900  assert(stat != NULL);
13901  assert(set != NULL);
13902  assert(var->scip == set->scip);
13903  assert(closestvlb != NULL);
13904  assert(closestvlbidx != NULL);
13905 
13906  *closestvlbidx = -1;
13907  *closestvlb = SCIP_REAL_MIN;
13908 
13909  nvlbs = SCIPvarGetNVlbs(var);
13910  if( nvlbs > 0 )
13911  {
13912  SCIP_VAR** vlbvars;
13913  SCIP_Real* vlbcoefs;
13914  SCIP_Real* vlbconsts;
13915  int i;
13916 
13917  vlbvars = SCIPvarGetVlbVars(var);
13918  vlbcoefs = SCIPvarGetVlbCoefs(var);
13919  vlbconsts = SCIPvarGetVlbConstants(var);
13920 
13921  /* check for cached values */
13922  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13923  {
13924  i = var->closestvlbidx;
13925  assert(0 <= i && i < nvlbs);
13926  assert(SCIPvarIsActive(vlbvars[i]));
13927  *closestvlbidx = i;
13928  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13929  }
13930  else
13931  {
13932  /* search best VUB */
13933  for( i = 0; i < nvlbs; i++ )
13934  {
13935  if( SCIPvarIsActive(vlbvars[i]) )
13936  {
13937  SCIP_Real vlbsol;
13938 
13939  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13940  if( vlbsol > *closestvlb )
13941  {
13942  *closestvlb = vlbsol;
13943  *closestvlbidx = i;
13944  }
13945  }
13946  }
13947 
13948  if( sol == NULL )
13949  {
13950  /* update cached value */
13951  if( var->closestvblpcount != stat->lpcount )
13952  var->closestvubidx = -1;
13953  var->closestvlbidx = *closestvlbidx;
13954  var->closestvblpcount = stat->lpcount;
13955  }
13956  }
13957  }
13958 }
13959 
13960 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13961  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13962  */
13964  SCIP_VAR* var, /**< active problem variable */
13965  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13966  SCIP_SET* set, /**< global SCIP settings */
13967  SCIP_STAT* stat, /**< problem statistics */
13968  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13969  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13970  )
13971 {
13972  int nvubs;
13973 
13974  assert(var != NULL);
13975  assert(set != NULL);
13976  assert(var->scip == set->scip);
13977  assert(closestvub != NULL);
13978  assert(closestvubidx != NULL);
13979 
13980  *closestvubidx = -1;
13981  *closestvub = SCIP_REAL_MAX;
13982 
13983  nvubs = SCIPvarGetNVubs(var);
13984  if( nvubs > 0 )
13985  {
13986  SCIP_VAR** vubvars;
13987  SCIP_Real* vubcoefs;
13988  SCIP_Real* vubconsts;
13989  int i;
13990 
13991  vubvars = SCIPvarGetVubVars(var);
13992  vubcoefs = SCIPvarGetVubCoefs(var);
13993  vubconsts = SCIPvarGetVubConstants(var);
13994 
13995  /* check for cached values */
13996  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13997  {
13998  i = var->closestvubidx;
13999  assert(0 <= i && i < nvubs);
14000  assert(SCIPvarIsActive(vubvars[i]));
14001  *closestvubidx = i;
14002  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
14003  }
14004  else
14005  {
14006  /* search best VUB */
14007  for( i = 0; i < nvubs; i++ )
14008  {
14009  if( SCIPvarIsActive(vubvars[i]) )
14010  {
14011  SCIP_Real vubsol;
14012 
14013  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
14014  if( vubsol < *closestvub )
14015  {
14016  *closestvub = vubsol;
14017  *closestvubidx = i;
14018  }
14019  }
14020  }
14021 
14022  if( sol == NULL )
14023  {
14024  /* update cached value */
14025  if( var->closestvblpcount != stat->lpcount )
14026  var->closestvlbidx = -1;
14027  var->closestvubidx = *closestvubidx;
14028  var->closestvblpcount = stat->lpcount;
14029  }
14030  }
14031  }
14032 }
14033 
14034 /** resolves variable to columns and adds them with the coefficient to the row */
14036  SCIP_VAR* var, /**< problem variable */
14037  BMS_BLKMEM* blkmem, /**< block memory */
14038  SCIP_SET* set, /**< global SCIP settings */
14039  SCIP_STAT* stat, /**< problem statistics */
14040  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
14041  SCIP_PROB* prob, /**< problem data */
14042  SCIP_LP* lp, /**< current LP data */
14043  SCIP_ROW* row, /**< LP row */
14044  SCIP_Real val /**< value of coefficient */
14045  )
14046 {
14047  int i;
14048 
14049  assert(var != NULL);
14050  assert(set != NULL);
14051  assert(var->scip == set->scip);
14052  assert(row != NULL);
14053  assert(!SCIPsetIsInfinity(set, REALABS(val)));
14054 
14055  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
14056 
14057  if ( SCIPsetIsZero(set, val) )
14058  return SCIP_OKAY;
14059 
14060  switch( SCIPvarGetStatus(var) )
14061  {
14063  if( var->data.original.transvar == NULL )
14064  {
14065  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
14066  return SCIP_INVALIDDATA;
14067  }
14068  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
14069  return SCIP_OKAY;
14070 
14071  case SCIP_VARSTATUS_LOOSE:
14072  /* add globally fixed variables as constant */
14073  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
14074  {
14075  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
14076  return SCIP_OKAY;
14077  }
14078  /* convert loose variable into column */
14079  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
14080  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
14081  /*lint -fallthrough*/
14082 
14083  case SCIP_VARSTATUS_COLUMN:
14084  assert(var->data.col != NULL);
14085  assert(var->data.col->var == var);
14086  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
14087  return SCIP_OKAY;
14088 
14089  case SCIP_VARSTATUS_FIXED:
14090  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
14091  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
14092  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
14093  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
14094  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
14095  return SCIP_OKAY;
14096 
14098  assert(var->data.aggregate.var != NULL);
14099  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
14100  row, var->data.aggregate.scalar * val) );
14101  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
14102  return SCIP_OKAY;
14103 
14105  assert(!var->donotmultaggr);
14106  assert(var->data.multaggr.vars != NULL);
14107  assert(var->data.multaggr.scalars != NULL);
14108  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
14109  * assert(var->data.multaggr.nvars >= 2);
14110  */
14111  for( i = 0; i < var->data.multaggr.nvars; ++i )
14112  {
14113  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
14114  row, var->data.multaggr.scalars[i] * val) );
14115  }
14116  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
14117  return SCIP_OKAY;
14118 
14119  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
14120  assert(var->negatedvar != NULL);
14122  assert(var->negatedvar->negatedvar == var);
14123  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
14124  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
14125  return SCIP_OKAY;
14126 
14127  default:
14128  SCIPerrorMessage("unknown variable status\n");
14129  return SCIP_INVALIDDATA;
14130  }
14131 }
14132 
14133 /* optionally, define this compiler flag to write complete variable histories to a file */
14134 #ifdef SCIP_HISTORYTOFILE
14135 SCIP_Longint counter = 0l;
14136 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
14137 #include "scip/scip.h"
14138 #endif
14139 
14140 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
14141  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
14142  */
14144  SCIP_VAR* var, /**< problem variable */
14145  SCIP_SET* set, /**< global SCIP settings */
14146  SCIP_STAT* stat, /**< problem statistics */
14147  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
14148  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
14149  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
14150  )
14151 {
14152  SCIP_Real oldrootpseudocosts;
14153  assert(var != NULL);
14154  assert(set != NULL);
14155  assert(var->scip == set->scip);
14156  assert(stat != NULL);
14157 
14158  /* check if history statistics should be collected for a variable */
14159  if( !stat->collectvarhistory )
14160  return SCIP_OKAY;
14161 
14162  switch( SCIPvarGetStatus(var) )
14163  {
14165  if( var->data.original.transvar == NULL )
14166  {
14167  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
14168  return SCIP_INVALIDDATA;
14169  }
14170  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
14171  return SCIP_OKAY;
14172 
14173  case SCIP_VARSTATUS_LOOSE:
14174  case SCIP_VARSTATUS_COLUMN:
14175  /* store old pseudo-costs for root LP best-estimate update */
14176  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
14177 
14178  /* update history */
14179  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
14180  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
14181  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
14182  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
14183 
14184  /* update root LP best-estimate */
14185  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
14186 
14187  /* append history to file */
14188 #ifdef SCIP_HISTORYTOFILE
14189  {
14190  FILE* f;
14191  char filename[256];
14192  SCIP_NODE* currentnode;
14193  SCIP_NODE* parentnode;
14194  currentnode = SCIPgetFocusNode(set->scip);
14195  parentnode = SCIPnodeGetParent(currentnode);
14196 
14197  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
14198  f = fopen(filename, "a");
14199  if( NULL != f )
14200  {
14201  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
14202  ++counter,
14203  SCIPvarGetName(var),
14204  SCIPnodeGetNumber(currentnode),
14205  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
14206  SCIPgetNLPIterations(set->scip),
14207  SCIPgetDepth(set->scip),
14208  objdelta,
14209  solvaldelta);
14210  fclose(f);
14211  }
14212  }
14213 #endif
14214  return SCIP_OKAY;
14215 
14216  case SCIP_VARSTATUS_FIXED:
14217  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
14218  return SCIP_INVALIDDATA;
14219 
14221  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
14223  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
14224  return SCIP_OKAY;
14225 
14227  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
14228  return SCIP_INVALIDDATA;
14229 
14231  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
14232  return SCIP_OKAY;
14233 
14234  default:
14235  SCIPerrorMessage("unknown variable status\n");
14236  return SCIP_INVALIDDATA;
14237  }
14238 }
14239 
14240 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
14242  SCIP_VAR* var, /**< problem variable */
14243  SCIP_STAT* stat, /**< problem statistics */
14244  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14245  )
14246 {
14247  SCIP_BRANCHDIR dir;
14248 
14249  assert(var != NULL);
14250  assert(stat != NULL);
14251 
14252  switch( SCIPvarGetStatus(var) )
14253  {
14255  if( var->data.original.transvar == NULL )
14256  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14257  else
14258  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
14259 
14260  case SCIP_VARSTATUS_LOOSE:
14261  case SCIP_VARSTATUS_COLUMN:
14262  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14263 
14264  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
14265  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
14266  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
14267 
14268  case SCIP_VARSTATUS_FIXED:
14269  return 0.0;
14270 
14272  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14273 
14275  return 0.0;
14276 
14278  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
14279 
14280  default:
14281  SCIPerrorMessage("unknown variable status\n");
14282  SCIPABORT();
14283  return 0.0; /*lint !e527*/
14284  }
14285 }
14286 
14287 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
14288  * only using the pseudo cost information of the current run
14289  */
14291  SCIP_VAR* var, /**< problem variable */
14292  SCIP_STAT* stat, /**< problem statistics */
14293  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
14294  )
14295 {
14296  SCIP_BRANCHDIR dir;
14297 
14298  assert(var != NULL);
14299  assert(stat != NULL);
14300 
14301  switch( SCIPvarGetStatus(var) )
14302  {
14304  if( var->data.original.transvar == NULL )
14305  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14306  else
14307  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
14308 
14309  case SCIP_VARSTATUS_LOOSE:
14310  case SCIP_VARSTATUS_COLUMN:
14311  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
14312 
14313  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
14314  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
14315  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
14316 
14317  case SCIP_VARSTATUS_FIXED:
14318  return 0.0;
14319 
14321  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
14322 
14324  return 0.0;
14325 
14327  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
14328 
14329  default:
14330  SCIPerrorMessage("unknown variable status\n");
14331  SCIPABORT();
14332  return 0.0; /*lint !e527*/
14333  }
14334 }
14335 
14336 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
14338  SCIP_VAR* var, /**< problem variable */
14339  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14340  )
14341 {
14342  assert(var != NULL);
14343  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14344 
14345  switch( SCIPvarGetStatus(var) )
14346  {
14348  if( var->data.original.transvar == NULL )
14349  return 0.0;
14350  else
14351  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
14352 
14353  case SCIP_VARSTATUS_LOOSE:
14354  case SCIP_VARSTATUS_COLUMN:
14355  return SCIPhistoryGetPseudocostCount(var->history, dir);
14356 
14357  case SCIP_VARSTATUS_FIXED:
14358  return 0.0;
14359 
14361  if( var->data.aggregate.scalar > 0.0 )
14362  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14363  else
14365 
14367  return 0.0;
14368 
14371 
14372  default:
14373  SCIPerrorMessage("unknown variable status\n");
14374  SCIPABORT();
14375  return 0.0; /*lint !e527*/
14376  }
14377 }
14378 
14379 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14380  * only using the pseudo cost information of the current run
14381  */
14383  SCIP_VAR* var, /**< problem variable */
14384  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14385  )
14386 {
14387  assert(var != NULL);
14388  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14389 
14390  switch( SCIPvarGetStatus(var) )
14391  {
14393  if( var->data.original.transvar == NULL )
14394  return 0.0;
14395  else
14397 
14398  case SCIP_VARSTATUS_LOOSE:
14399  case SCIP_VARSTATUS_COLUMN:
14400  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14401 
14402  case SCIP_VARSTATUS_FIXED:
14403  return 0.0;
14404 
14406  if( var->data.aggregate.scalar > 0.0 )
14408  else
14410 
14412  return 0.0;
14413 
14416 
14417  default:
14418  SCIPerrorMessage("unknown variable status\n");
14419  SCIPABORT();
14420  return 0.0; /*lint !e527*/
14421  }
14422 }
14423 
14424 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14426  SCIP_VAR* var, /**< problem variable */
14427  SCIP_STAT* stat, /**< problem statistics */
14428  SCIP_SET* set, /**< global SCIP settings */
14429  SCIP_Real solval /**< solution value, e.g., LP solution value */
14430  )
14431 {
14432  SCIP_Real upscore;
14433  SCIP_Real downscore;
14434  SCIP_Real solvaldeltaup;
14435  SCIP_Real solvaldeltadown;
14436 
14437  /* LP root estimate only works for variables with fractional LP root solution */
14438  if( SCIPsetIsFeasIntegral(set, solval) )
14439  return 0.0;
14440 
14441  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14443  return 0.0;
14444 
14445  /* compute delta's to ceil and floor of root LP solution value */
14446  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14447  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14448 
14449  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14450  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14451 
14452  return MIN(upscore, downscore);
14453 }
14454 
14455 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14457  SCIP_VAR* var, /**< problem variable */
14458  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14459  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14460  )
14461 {
14462  assert(var != NULL);
14463  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14464 
14465  switch( SCIPvarGetStatus(var) )
14466  {
14468  if( var->data.original.transvar == NULL )
14469  return 0.0;
14470  else
14471  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14472 
14473  case SCIP_VARSTATUS_LOOSE:
14474  case SCIP_VARSTATUS_COLUMN:
14475  if( onlycurrentrun )
14477  else
14478  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14479 
14480  case SCIP_VARSTATUS_FIXED:
14481  return 0.0;
14482 
14484  if( var->data.aggregate.scalar > 0.0 )
14485  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14486  else
14487  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14488 
14490  return 0.0;
14491 
14493  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14494 
14495  default:
14496  SCIPerrorMessage("unknown variable status\n");
14497  SCIPABORT();
14498  return 0.0; /*lint !e527*/
14499  }
14500 }
14501 
14502 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14503  *
14504  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14505  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14506  * of 2 * clevel - 1.
14507  *
14508  * @return value of confidence bound for this variable
14509  */
14511  SCIP_VAR* var, /**< variable in question */
14512  SCIP_SET* set, /**< global SCIP settings */
14513  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14514  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14515  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14516  )
14517 {
14518  SCIP_Real confidencebound;
14519 
14520  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14521  if( SCIPsetIsFeasPositive(set, confidencebound) )
14522  {
14523  SCIP_Real count;
14524 
14525  if( onlycurrentrun )
14526  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14527  else
14528  count = SCIPvarGetPseudocostCount(var, dir);
14529  /* assertion is valid because variance is positive */
14530  assert(count >= 1.9);
14531 
14532  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14533  confidencebound = sqrt(confidencebound);
14534 
14535  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14536  * the number of pseudo cost evaluations of this variable in the respective direction. */
14537  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14538  }
14539  else
14540  confidencebound = 0.0;
14541 
14542  return confidencebound;
14543 }
14544 
14545 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14546  * Error is calculated at a specific confidence level
14547  */
14549  SCIP_VAR* var, /**< variable in question */
14550  SCIP_SET* set, /**< global SCIP settings */
14551  SCIP_STAT* stat, /**< problem statistics */
14552  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14553  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14554  )
14555 {
14556  SCIP_Real downsize;
14557  SCIP_Real upsize;
14558  SCIP_Real size;
14559  SCIP_Real relerrorup;
14560  SCIP_Real relerrordown;
14561  SCIP_Real relerror;
14562 
14563  /* check, if the pseudo cost score of the variable is reliable */
14566  size = MIN(downsize, upsize);
14567 
14568  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14569  if( size <= 1.9 )
14570  return FALSE;
14571 
14572  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14573  * confidence interval bound at confidence level of 95% for individual variable reliability.
14574  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14575  */
14576  if( downsize >= 1.9 )
14577  {
14578  SCIP_Real normval;
14579 
14580  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14581  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14582  normval = MAX(1.0, normval);
14583 
14584  relerrordown /= normval;
14585  }
14586  else
14587  relerrordown = 0.0;
14588 
14589  if( upsize >= 1.9 )
14590  {
14591  SCIP_Real normval;
14592 
14593  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14594  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14595  normval = MAX(1.0, normval);
14596  relerrorup /= normval;
14597  }
14598  else
14599  relerrorup = 0.0;
14600 
14601  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14602  relerror = MAX(relerrorup, relerrordown);
14603 
14604  return (relerror <= threshold);
14605 }
14606 
14607 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14608  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14609  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14610  * unknown location means of the underlying pseudo-cost distributions of x and y.
14611  *
14612  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14613  * better than x (despite the current information), meaning that y can be expected to yield branching
14614  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14615  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14616  * than y.
14617  *
14618  * @note The order of x and y matters for the one-sided hypothesis
14619  *
14620  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14621  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14622  *
14623  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14624  */
14626  SCIP_SET* set, /**< global SCIP settings */
14627  SCIP_STAT* stat, /**< problem statistics */
14628  SCIP_VAR* varx, /**< variable x */
14629  SCIP_Real fracx, /**< the fractionality of variable x */
14630  SCIP_VAR* vary, /**< variable y */
14631  SCIP_Real fracy, /**< the fractionality of variable y */
14632  SCIP_BRANCHDIR dir, /**< branching direction */
14633  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14634  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14635  )
14636 {
14637  SCIP_Real meanx;
14638  SCIP_Real meany;
14639  SCIP_Real variancex;
14640  SCIP_Real variancey;
14641  SCIP_Real countx;
14642  SCIP_Real county;
14643  SCIP_Real tresult;
14644  SCIP_Real realdirection;
14645 
14646  if( varx == vary )
14647  return FALSE;
14648 
14649  countx = SCIPvarGetPseudocostCount(varx, dir);
14650  county = SCIPvarGetPseudocostCount(vary, dir);
14651 
14652  /* if not at least 2 measurements were taken, return FALSE */
14653  if( countx <= 1.9 || county <= 1.9 )
14654  return FALSE;
14655 
14656  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14657 
14658  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14659  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14660 
14661  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14662  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14663 
14664  /* if there is no variance, the means are taken from a constant distribution */
14665  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14666  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14667 
14668  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14669 
14670  /* for the two-sided hypothesis, just take the absolute of t */
14671  if( !onesided )
14672  tresult = REALABS(tresult);
14673 
14674  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14675 }
14676 
14677 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14678  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14679  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14680  * of at least \p threshold.
14681  *
14682  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14683  * the estimated probability to exceed \p threshold is less than 25 %.
14684  *
14685  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14686  * of confidence.
14687  *
14688  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14689  * at the given confidence level \p clevel.
14690  */
14692  SCIP_SET* set, /**< global SCIP settings */
14693  SCIP_STAT* stat, /**< problem statistics */
14694  SCIP_VAR* var, /**< variable x */
14695  SCIP_Real frac, /**< the fractionality of variable x */
14696  SCIP_Real threshold, /**< the threshold to test against */
14697  SCIP_BRANCHDIR dir, /**< branching direction */
14698  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14699  )
14700 {
14701  SCIP_Real mean;
14702  SCIP_Real variance;
14703  SCIP_Real count;
14704  SCIP_Real realdirection;
14705  SCIP_Real probability;
14706  SCIP_Real problimit;
14707 
14708  count = SCIPvarGetPseudocostCount(var, dir);
14709 
14710  /* if not at least 2 measurements were taken, return FALSE */
14711  if( count <= 1.9 )
14712  return FALSE;
14713 
14714  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14715 
14716  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14717  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14718 
14719  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14720  if( SCIPsetIsFeasGE(set, mean, threshold) )
14721  return FALSE;
14722 
14723  /* if there is no variance, the means are taken from a constant distribution */
14724  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14725  return SCIPsetIsFeasLT(set, mean, threshold);
14726 
14727  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14728  probability = SCIPnormalCDF(mean, variance, threshold);
14729 
14730  /* determine a probability limit corresponding to the given confidence level */
14731  switch( clevel )
14732  {
14734  problimit = 0.75;
14735  break;
14737  problimit = 0.875;
14738  break;
14740  problimit = 0.9;
14741  break;
14743  problimit = 0.95;
14744  break;
14746  problimit = 0.975;
14747  break;
14748  default:
14749  problimit = -1;
14750  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14751  SCIPABORT();
14752  break;
14753  }
14754 
14755  return (probability >= problimit);
14756 }
14757 
14758 /** find the corresponding history entry if already existing, otherwise create new entry */
14759 static
14761  SCIP_VAR* var, /**< problem variable */
14762  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14763  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14764  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14765  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14766  )
14767 {
14768  assert(var != NULL);
14769  assert(blkmem != NULL);
14770  assert(set != NULL);
14771  assert(history != NULL);
14772 
14773  (*history) = NULL;
14774 
14775  if( var->valuehistory == NULL )
14776  {
14777  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14778  }
14779 
14780  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14781 
14782  return SCIP_OKAY;
14783 }
14784 
14785 /** check if value based history should be used */
14786 static
14788  SCIP_VAR* var, /**< problem variable */
14789  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14790  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14791  )
14792 {
14793  /* check if the domain value is unknown (not specific) */
14794  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14795  return FALSE;
14796 
14797  assert(set != NULL);
14798 
14799  /* check if value based history should be collected */
14800  if( !set->history_valuebased )
14801  return FALSE;
14802 
14803  /* value based history is not collected for binary variable since the standard history already contains all information */
14804  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14805  return FALSE;
14806 
14807  /* value based history is not collected for continuous variables */
14809  return FALSE;
14810 
14811  return TRUE;
14812 }
14813 
14814 /** increases VSIDS of the variable by the given weight */
14816  SCIP_VAR* var, /**< problem variable */
14817  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14818  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14819  SCIP_STAT* stat, /**< problem statistics */
14820  SCIP_BRANCHDIR dir, /**< branching direction */
14821  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14822  SCIP_Real weight /**< weight of this update in VSIDS */
14823  )
14824 {
14825  assert(var != NULL);
14826  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14827 
14828  /* check if history statistics should be collected for a variable */
14829  if( !stat->collectvarhistory )
14830  return SCIP_OKAY;
14831 
14832  if( SCIPsetIsZero(set, weight) )
14833  return SCIP_OKAY;
14834 
14835  switch( SCIPvarGetStatus(var) )
14836  {
14838  if( var->data.original.transvar == NULL )
14839  {
14840  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14841  return SCIP_INVALIDDATA;
14842  }
14843  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14844  return SCIP_OKAY;
14845 
14846  case SCIP_VARSTATUS_LOOSE:
14847  case SCIP_VARSTATUS_COLUMN:
14848  {
14849  SCIPhistoryIncVSIDS(var->history, dir, weight);
14850  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14851 
14852  if( useValuehistory(var, value, set) )
14853  {
14854  SCIP_HISTORY* history;
14855 
14856  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14857  assert(history != NULL);
14858 
14859  SCIPhistoryIncVSIDS(history, dir, weight);
14860  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14861  value, weight, SCIPhistoryGetVSIDS(history, dir));
14862  }
14863 
14864  return SCIP_OKAY;
14865  }
14866  case SCIP_VARSTATUS_FIXED:
14867  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14868  return SCIP_INVALIDDATA;
14869 
14871  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14872 
14873  if( var->data.aggregate.scalar > 0.0 )
14874  {
14875  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14876  }
14877  else
14878  {
14879  assert(var->data.aggregate.scalar < 0.0);
14880  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14881  }
14882  return SCIP_OKAY;
14883 
14885  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14886  return SCIP_INVALIDDATA;
14887 
14889  value = 1.0 - value;
14890 
14891  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14892  return SCIP_OKAY;
14893 
14894  default:
14895  SCIPerrorMessage("unknown variable status\n");
14896  return SCIP_INVALIDDATA;
14897  }
14898 }
14899 
14900 /** scales the VSIDS of the variable by the given scalar */
14902  SCIP_VAR* var, /**< problem variable */
14903  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14904  )
14905 {
14906  assert(var != NULL);
14907 
14908  switch( SCIPvarGetStatus(var) )
14909  {
14911  if( var->data.original.transvar == NULL )
14912  {
14913  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14914  return SCIP_INVALIDDATA;
14915  }
14917  return SCIP_OKAY;
14918 
14919  case SCIP_VARSTATUS_LOOSE:
14920  case SCIP_VARSTATUS_COLUMN:
14921  {
14922  SCIPhistoryScaleVSIDS(var->history, scalar);
14923  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14925 
14926  return SCIP_OKAY;
14927  }
14928  case SCIP_VARSTATUS_FIXED:
14929  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14930  return SCIP_INVALIDDATA;
14931 
14933  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14934  return SCIP_OKAY;
14935 
14937  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14938  return SCIP_INVALIDDATA;
14939 
14941  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14942  return SCIP_OKAY;
14943 
14944  default:
14945  SCIPerrorMessage("unknown variable status\n");
14946  return SCIP_INVALIDDATA;
14947  }
14948 }
14949 
14950 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14952  SCIP_VAR* var, /**< problem variable */
14953  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14954  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14955  SCIP_STAT* stat, /**< problem statistics */
14956  SCIP_BRANCHDIR dir, /**< branching direction */
14957  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14958  SCIP_Real length /**< length of the conflict */
14959  )
14960 {
14961  assert(var != NULL);
14962  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14963 
14964  /* check if history statistics should be collected for a variable */
14965  if( !stat->collectvarhistory )
14966  return SCIP_OKAY;
14967 
14968  switch( SCIPvarGetStatus(var) )
14969  {
14971  if( var->data.original.transvar == NULL )
14972  {
14973  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14974  return SCIP_INVALIDDATA;
14975  }
14976  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14977  return SCIP_OKAY;
14978 
14979  case SCIP_VARSTATUS_LOOSE:
14980  case SCIP_VARSTATUS_COLUMN:
14981  {
14982  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14983  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14984 
14985  if( useValuehistory(var, value, set) )
14986  {
14987  SCIP_HISTORY* history;
14988 
14989  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14990  assert(history != NULL);
14991 
14992  SCIPhistoryIncNActiveConflicts(history, dir, length);
14993  }
14994 
14995  return SCIP_OKAY;
14996  }
14997  case SCIP_VARSTATUS_FIXED:
14998  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14999  return SCIP_INVALIDDATA;
15000 
15002  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15003 
15004  if( var->data.aggregate.scalar > 0.0 )
15005  {
15006  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
15007  }
15008  else
15009  {
15010  assert(var->data.aggregate.scalar < 0.0);
15011  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15012  }
15013  return SCIP_OKAY;
15014 
15016  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
15017  return SCIP_INVALIDDATA;
15018 
15020  value = 1.0 - value;
15021 
15022  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
15023  return SCIP_OKAY;
15024 
15025  default:
15026  SCIPerrorMessage("unknown variable status\n");
15027  return SCIP_INVALIDDATA;
15028  }
15029 }
15030 
15031 /** gets the number of active conflicts containing this variable in given direction */
15033  SCIP_VAR* var, /**< problem variable */
15034  SCIP_STAT* stat, /**< problem statistics */
15035  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15036  )
15037 {
15038  assert(var != NULL);
15039  assert(stat != NULL);
15040  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15041 
15042  switch( SCIPvarGetStatus(var) )
15043  {
15045  if( var->data.original.transvar == NULL )
15046  return 0;
15047  else
15048  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
15049 
15050  case SCIP_VARSTATUS_LOOSE:
15051  case SCIP_VARSTATUS_COLUMN:
15052  return SCIPhistoryGetNActiveConflicts(var->history, dir);
15053 
15054  case SCIP_VARSTATUS_FIXED:
15055  return 0;
15056 
15058  if( var->data.aggregate.scalar > 0.0 )
15059  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
15060  else
15062 
15064  return 0;
15065 
15068 
15069  default:
15070  SCIPerrorMessage("unknown variable status\n");
15071  SCIPABORT();
15072  return 0; /*lint !e527*/
15073  }
15074 }
15075 
15076 /** gets the number of active conflicts containing this variable in given direction
15077  * in the current run
15078  */
15080  SCIP_VAR* var, /**< problem variable */
15081  SCIP_STAT* stat, /**< problem statistics */
15082  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15083  )
15084 {
15085  assert(var != NULL);
15086  assert(stat != NULL);
15087  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15088 
15089  switch( SCIPvarGetStatus(var) )
15090  {
15092  if( var->data.original.transvar == NULL )
15093  return 0;
15094  else
15096 
15097  case SCIP_VARSTATUS_LOOSE:
15098  case SCIP_VARSTATUS_COLUMN:
15099  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
15100 
15101  case SCIP_VARSTATUS_FIXED:
15102  return 0;
15103 
15105  if( var->data.aggregate.scalar > 0.0 )
15106  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
15107  else
15109 
15111  return 0;
15112 
15115 
15116  default:
15117  SCIPerrorMessage("unknown variable status\n");
15118  SCIPABORT();
15119  return 0; /*lint !e527*/
15120  }
15121 }
15122 
15123 /** gets the average conflict length in given direction due to branching on the variable */
15125  SCIP_VAR* var, /**< problem variable */
15126  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15127  )
15128 {
15129  assert(var != NULL);
15130  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15131 
15132  switch( SCIPvarGetStatus(var) )
15133  {
15135  if( var->data.original.transvar == NULL )
15136  return 0.0;
15137  else
15139 
15140  case SCIP_VARSTATUS_LOOSE:
15141  case SCIP_VARSTATUS_COLUMN:
15142  return SCIPhistoryGetAvgConflictlength(var->history, dir);
15143  case SCIP_VARSTATUS_FIXED:
15144  return 0.0;
15145 
15147  if( var->data.aggregate.scalar > 0.0 )
15148  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
15149  else
15151 
15153  return 0.0;
15154 
15157 
15158  default:
15159  SCIPerrorMessage("unknown variable status\n");
15160  SCIPABORT();
15161  return 0.0; /*lint !e527*/
15162  }
15163 }
15164 
15165 /** gets the average conflict length in given direction due to branching on the variable
15166  * in the current run
15167  */
15169  SCIP_VAR* var, /**< problem variable */
15170  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15171  )
15172 {
15173  assert(var != NULL);
15174  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15175 
15176  switch( SCIPvarGetStatus(var) )
15177  {
15179  if( var->data.original.transvar == NULL )
15180  return 0.0;
15181  else
15183 
15184  case SCIP_VARSTATUS_LOOSE:
15185  case SCIP_VARSTATUS_COLUMN:
15186  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
15187 
15188  case SCIP_VARSTATUS_FIXED:
15189  return 0.0;
15190 
15192  if( var->data.aggregate.scalar > 0.0 )
15194  else
15196 
15198  return 0.0;
15199 
15202 
15203  default:
15204  SCIPerrorMessage("unknown variable status\n");
15205  SCIPABORT();
15206  return 0.0; /*lint !e527*/
15207  }
15208 }
15209 
15210 /** increases the number of branchings counter of the variable */
15212  SCIP_VAR* var, /**< problem variable */
15213  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15214  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15215  SCIP_STAT* stat, /**< problem statistics */
15216  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15217  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15218  int depth /**< depth at which the bound change took place */
15219  )
15220 {
15221  assert(var != NULL);
15222  assert(stat != NULL);
15223  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15224 
15225  /* check if history statistics should be collected for a variable */
15226  if( !stat->collectvarhistory )
15227  return SCIP_OKAY;
15228 
15229  switch( SCIPvarGetStatus(var) )
15230  {
15232  if( var->data.original.transvar == NULL )
15233  {
15234  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
15235  return SCIP_INVALIDDATA;
15236  }
15237  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
15238  return SCIP_OKAY;
15239 
15240  case SCIP_VARSTATUS_LOOSE:
15241  case SCIP_VARSTATUS_COLUMN:
15242  {
15243  SCIPhistoryIncNBranchings(var->history, dir, depth);
15244  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
15245  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
15246  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
15247 
15248  if( useValuehistory(var, value, set) )
15249  {
15250  SCIP_HISTORY* history;
15251 
15252  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15253  assert(history != NULL);
15254 
15255  SCIPhistoryIncNBranchings(history, dir, depth);
15256  }
15257 
15258  return SCIP_OKAY;
15259  }
15260  case SCIP_VARSTATUS_FIXED:
15261  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
15262  return SCIP_INVALIDDATA;
15263 
15265  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15266 
15267  if( var->data.aggregate.scalar > 0.0 )
15268  {
15269  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
15270  }
15271  else
15272  {
15273  assert(var->data.aggregate.scalar < 0.0);
15274  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15275  }
15276  return SCIP_OKAY;
15277 
15279  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
15280  return SCIP_INVALIDDATA;
15281 
15283  value = 1.0 - value;
15284 
15285  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
15286  return SCIP_OKAY;
15287 
15288  default:
15289  SCIPerrorMessage("unknown variable status\n");
15290  return SCIP_INVALIDDATA;
15291  }
15292 }
15293 
15294 /** increases the inference sum of the variable by the given weight */
15296  SCIP_VAR* var, /**< problem variable */
15297  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15298  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15299  SCIP_STAT* stat, /**< problem statistics */
15300  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15301  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15302  SCIP_Real weight /**< weight of this update in inference score */
15303  )
15304 {
15305  assert(var != NULL);
15306  assert(stat != NULL);
15307  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15308 
15309  /* check if history statistics should be collected for a variable */
15310  if( !stat->collectvarhistory )
15311  return SCIP_OKAY;
15312 
15313  switch( SCIPvarGetStatus(var) )
15314  {
15316  if( var->data.original.transvar == NULL )
15317  {
15318  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
15319  return SCIP_INVALIDDATA;
15320  }
15321  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15322  return SCIP_OKAY;
15323 
15324  case SCIP_VARSTATUS_LOOSE:
15325  case SCIP_VARSTATUS_COLUMN:
15326  {
15327  SCIPhistoryIncInferenceSum(var->history, dir, weight);
15328  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
15329  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
15330  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
15331 
15332  if( useValuehistory(var, value, set) )
15333  {
15334  SCIP_HISTORY* history;
15335 
15336  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15337  assert(history != NULL);
15338 
15339  SCIPhistoryIncInferenceSum(history, dir, weight);
15340  }
15341 
15342  return SCIP_OKAY;
15343  }
15344  case SCIP_VARSTATUS_FIXED:
15345  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
15346  return SCIP_INVALIDDATA;
15347 
15349  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15350 
15351  if( var->data.aggregate.scalar > 0.0 )
15352  {
15353  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15354  }
15355  else
15356  {
15357  assert(var->data.aggregate.scalar < 0.0);
15358  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15359  }
15360  return SCIP_OKAY;
15361 
15363  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15364  return SCIP_INVALIDDATA;
15365 
15367  value = 1.0 - value;
15368 
15369  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15370  return SCIP_OKAY;
15371 
15372  default:
15373  SCIPerrorMessage("unknown variable status\n");
15374  return SCIP_INVALIDDATA;
15375  }
15376 }
15377 
15378 /** increases the cutoff sum of the variable by the given weight */
15380  SCIP_VAR* var, /**< problem variable */
15381  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15382  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15383  SCIP_STAT* stat, /**< problem statistics */
15384  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15385  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15386  SCIP_Real weight /**< weight of this update in cutoff score */
15387  )
15388 {
15389  assert(var != NULL);
15390  assert(stat != NULL);
15391  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15392 
15393  /* check if history statistics should be collected for a variable */
15394  if( !stat->collectvarhistory )
15395  return SCIP_OKAY;
15396 
15397  switch( SCIPvarGetStatus(var) )
15398  {
15400  if( var->data.original.transvar == NULL )
15401  {
15402  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15403  return SCIP_INVALIDDATA;
15404  }
15405  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15406  return SCIP_OKAY;
15407 
15408  case SCIP_VARSTATUS_LOOSE:
15409  case SCIP_VARSTATUS_COLUMN:
15410  {
15411  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15412  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15413  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15414  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15415 
15416  if( useValuehistory(var, value, set) )
15417  {
15418  SCIP_HISTORY* history;
15419 
15420  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15421  assert(history != NULL);
15422 
15423  SCIPhistoryIncCutoffSum(history, dir, weight);
15424  }
15425 
15426  return SCIP_OKAY;
15427  }
15428  case SCIP_VARSTATUS_FIXED:
15429  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15430  return SCIP_INVALIDDATA;
15431 
15433  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15434 
15435  if( var->data.aggregate.scalar > 0.0 )
15436  {
15437  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15438  }
15439  else
15440  {
15441  assert(var->data.aggregate.scalar < 0.0);
15442  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15443  }
15444  return SCIP_OKAY;
15445 
15447  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15448  return SCIP_INVALIDDATA;
15449 
15451  value = 1.0 - value;
15452 
15453  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15454  return SCIP_OKAY;
15455 
15456  default:
15457  SCIPerrorMessage("unknown variable status\n");
15458  return SCIP_INVALIDDATA;
15459  }
15460 }
15461 
15462 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15464  SCIP_VAR* var, /**< problem variable */
15465  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15466  )
15467 {
15468  assert(var != NULL);
15469  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15470 
15471  switch( SCIPvarGetStatus(var) )
15472  {
15474  if( var->data.original.transvar == NULL )
15475  return 0;
15476  else
15477  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15478 
15479  case SCIP_VARSTATUS_LOOSE:
15480  case SCIP_VARSTATUS_COLUMN:
15481  return SCIPhistoryGetNBranchings(var->history, dir);
15482 
15483  case SCIP_VARSTATUS_FIXED:
15484  return 0;
15485 
15487  if( var->data.aggregate.scalar > 0.0 )
15488  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15489  else
15491 
15493  return 0;
15494 
15497 
15498  default:
15499  SCIPerrorMessage("unknown variable status\n");
15500  SCIPABORT();
15501  return 0; /*lint !e527*/
15502  }
15503 }
15504 
15505 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15506  * in the current run
15507  */
15509  SCIP_VAR* var, /**< problem variable */
15510  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15511  )
15512 {
15513  assert(var != NULL);
15514  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15515 
15516  switch( SCIPvarGetStatus(var) )
15517  {
15519  if( var->data.original.transvar == NULL )
15520  return 0;
15521  else
15523 
15524  case SCIP_VARSTATUS_LOOSE:
15525  case SCIP_VARSTATUS_COLUMN:
15526  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15527 
15528  case SCIP_VARSTATUS_FIXED:
15529  return 0;
15530 
15532  if( var->data.aggregate.scalar > 0.0 )
15534  else
15536 
15538  return 0;
15539 
15542 
15543  default:
15544  SCIPerrorMessage("unknown variable status\n");
15545  SCIPABORT();
15546  return 0; /*lint !e527*/
15547  }
15548 }
15549 
15550 /** returns the average depth of bound changes in given direction due to branching on the variable */
15552  SCIP_VAR* var, /**< problem variable */
15553  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15554  )
15555 {
15556  assert(var != NULL);
15557  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15558 
15559  switch( SCIPvarGetStatus(var) )
15560  {
15562  if( var->data.original.transvar == NULL )
15563  return 0.0;
15564  else
15565  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15566 
15567  case SCIP_VARSTATUS_LOOSE:
15568  case SCIP_VARSTATUS_COLUMN:
15569  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15570 
15571  case SCIP_VARSTATUS_FIXED:
15572  return 0.0;
15573 
15575  if( var->data.aggregate.scalar > 0.0 )
15576  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15577  else
15579 
15581  return 0.0;
15582 
15585 
15586  default:
15587  SCIPerrorMessage("unknown variable status\n");
15588  SCIPABORT();
15589  return 0.0; /*lint !e527*/
15590  }
15591 }
15592 
15593 /** returns the average depth of bound changes in given direction due to branching on the variable
15594  * in the current run
15595  */
15597  SCIP_VAR* var, /**< problem variable */
15598  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15599  )
15600 {
15601  assert(var != NULL);
15602  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15603 
15604  switch( SCIPvarGetStatus(var) )
15605  {
15607  if( var->data.original.transvar == NULL )
15608  return 0.0;
15609  else
15611 
15612  case SCIP_VARSTATUS_LOOSE:
15613  case SCIP_VARSTATUS_COLUMN:
15614  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15615 
15616  case SCIP_VARSTATUS_FIXED:
15617  return 0.0;
15618 
15620  if( var->data.aggregate.scalar > 0.0 )
15622  else
15625 
15627  return 0.0;
15628 
15631  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15632 
15633  default:
15634  SCIPerrorMessage("unknown variable status\n");
15635  SCIPABORT();
15636  return 0.0; /*lint !e527*/
15637  }
15638 }
15639 
15640 /** returns the variable's VSIDS score */
15642  SCIP_VAR* var, /**< problem variable */
15643  SCIP_STAT* stat, /**< problem statistics */
15644  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15645  )
15646 {
15647  assert(var != NULL);
15648  assert(stat != NULL);
15649  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15650 
15652  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15653 
15654  switch( SCIPvarGetStatus(var) )
15655  {
15657  if( var->data.original.transvar == NULL )
15658  return 0.0;
15659  else
15660  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15661 
15662  case SCIP_VARSTATUS_LOOSE:
15663  case SCIP_VARSTATUS_COLUMN:
15664  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15665  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15666 
15667  case SCIP_VARSTATUS_FIXED:
15668  return 0.0;
15669 
15671  if( var->data.aggregate.scalar > 0.0 )
15672  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15673  else
15674  /* coverity[overrun-local] */
15675  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15676 
15678  return 0.0;
15679 
15681  /* coverity[overrun-local] */
15682  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15683 
15684  default:
15685  SCIPerrorMessage("unknown variable status\n");
15686  SCIPABORT();
15687  return 0.0; /*lint !e527*/
15688  }
15689 }
15690 
15691 /** returns the variable's VSIDS score only using conflicts of the current run */
15693  SCIP_VAR* var, /**< problem variable */
15694  SCIP_STAT* stat, /**< problem statistics */
15695  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15696  )
15697 {
15698  assert(var != NULL);
15699  assert(stat != NULL);
15700  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15701 
15702  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15703  {
15704  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15705  return SCIP_INVALID;
15706  }
15707 
15708  switch( SCIPvarGetStatus(var) )
15709  {
15711  if( var->data.original.transvar == NULL )
15712  return 0.0;
15713  else
15714  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15715 
15716  case SCIP_VARSTATUS_LOOSE:
15717  case SCIP_VARSTATUS_COLUMN:
15718  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15719 
15720  case SCIP_VARSTATUS_FIXED:
15721  return 0.0;
15722 
15724  if( var->data.aggregate.scalar > 0.0 )
15725  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15726  else
15728 
15730  return 0.0;
15731 
15734 
15735  default:
15736  SCIPerrorMessage("unknown variable status\n");
15737  SCIPABORT();
15738  return 0.0; /*lint !e527*/
15739  }
15740 }
15741 
15742 /** returns the number of inferences branching on this variable in given direction triggered */
15744  SCIP_VAR* var, /**< problem variable */
15745  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15746  )
15747 {
15748  assert(var != NULL);
15749  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15750 
15751  switch( SCIPvarGetStatus(var) )
15752  {
15754  if( var->data.original.transvar == NULL )
15755  return 0.0;
15756  else
15757  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15758 
15759  case SCIP_VARSTATUS_LOOSE:
15760  case SCIP_VARSTATUS_COLUMN:
15761  return SCIPhistoryGetInferenceSum(var->history, dir);
15762 
15763  case SCIP_VARSTATUS_FIXED:
15764  return 0.0;
15765 
15767  if( var->data.aggregate.scalar > 0.0 )
15768  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15769  else
15771 
15773  return 0.0;
15774 
15777 
15778  default:
15779  SCIPerrorMessage("unknown variable status\n");
15780  SCIPABORT();
15781  return 0.0; /*lint !e527*/
15782  }
15783 }
15784 
15785 /** returns the number of inferences branching on this variable in given direction triggered
15786  * in the current run
15787  */
15789  SCIP_VAR* var, /**< problem variable */
15790  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15791  )
15792 {
15793  assert(var != NULL);
15794  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15795 
15796  switch( SCIPvarGetStatus(var) )
15797  {
15799  if( var->data.original.transvar == NULL )
15800  return 0.0;
15801  else
15803 
15804  case SCIP_VARSTATUS_LOOSE:
15805  case SCIP_VARSTATUS_COLUMN:
15806  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15807 
15808  case SCIP_VARSTATUS_FIXED:
15809  return 0.0;
15810 
15812  if( var->data.aggregate.scalar > 0.0 )
15814  else
15816 
15818  return 0.0;
15819 
15822 
15823  default:
15824  SCIPerrorMessage("unknown variable status\n");
15825  SCIPABORT();
15826  return 0.0; /*lint !e527*/
15827  }
15828 }
15829 
15830 /** returns the average number of inferences found after branching on the variable in given direction */
15832  SCIP_VAR* var, /**< problem variable */
15833  SCIP_STAT* stat, /**< problem statistics */
15834  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15835  )
15836 {
15837  assert(var != NULL);
15838  assert(stat != NULL);
15839  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15840 
15841  switch( SCIPvarGetStatus(var) )
15842  {
15844  if( var->data.original.transvar == NULL )
15845  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15846  else
15847  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15848 
15849  case SCIP_VARSTATUS_LOOSE:
15850  case SCIP_VARSTATUS_COLUMN:
15851  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15852  return SCIPhistoryGetAvgInferences(var->history, dir);
15853  else
15854  {
15855  int nimpls;
15856  int ncliques;
15857 
15858  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15859  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15860  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15861  }
15862 
15863  case SCIP_VARSTATUS_FIXED:
15864  return 0.0;
15865 
15867  if( var->data.aggregate.scalar > 0.0 )
15868  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15869  else
15871 
15873  return 0.0;
15874 
15876  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15877 
15878  default:
15879  SCIPerrorMessage("unknown variable status\n");
15880  SCIPABORT();
15881  return 0.0; /*lint !e527*/
15882  }
15883 }
15884 
15885 /** returns the average number of inferences found after branching on the variable in given direction
15886  * in the current run
15887  */
15889  SCIP_VAR* var, /**< problem variable */
15890  SCIP_STAT* stat, /**< problem statistics */
15891  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15892  )
15893 {
15894  assert(var != NULL);
15895  assert(stat != NULL);
15896  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15897 
15898  switch( SCIPvarGetStatus(var) )
15899  {
15901  if( var->data.original.transvar == NULL )
15902  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15903  else
15904  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15905 
15906  case SCIP_VARSTATUS_LOOSE:
15907  case SCIP_VARSTATUS_COLUMN:
15908  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15909  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15910  else
15911  {
15912  int nimpls;
15913  int ncliques;
15914 
15915  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15916  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15917  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15918  }
15919 
15920  case SCIP_VARSTATUS_FIXED:
15921  return 0.0;
15922 
15924  if( var->data.aggregate.scalar > 0.0 )
15925  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15926  else
15928 
15930  return 0.0;
15931 
15934 
15935  default:
15936  SCIPerrorMessage("unknown variable status\n");
15937  SCIPABORT();
15938  return 0.0; /*lint !e527*/
15939  }
15940 }
15941 
15942 /** returns the number of cutoffs branching on this variable in given direction produced */
15944  SCIP_VAR* var, /**< problem variable */
15945  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15946  )
15947 {
15948  assert(var != NULL);
15949  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15950 
15951  switch( SCIPvarGetStatus(var) )
15952  {
15954  if( var->data.original.transvar == NULL )
15955  return 0;
15956  else
15957  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15958 
15959  case SCIP_VARSTATUS_LOOSE:
15960  case SCIP_VARSTATUS_COLUMN:
15961  return SCIPhistoryGetCutoffSum(var->history, dir);
15962 
15963  case SCIP_VARSTATUS_FIXED:
15964  return 0;
15965 
15967  if( var->data.aggregate.scalar > 0.0 )
15968  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15969  else
15971 
15973  return 0;
15974 
15977 
15978  default:
15979  SCIPerrorMessage("unknown variable status\n");
15980  SCIPABORT();
15981  return 0; /*lint !e527*/
15982  }
15983 }
15984 
15985 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15987  SCIP_VAR* var, /**< problem variable */
15988  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15989  )
15990 {
15991  assert(var != NULL);
15992  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15993 
15994  switch( SCIPvarGetStatus(var) )
15995  {
15997  if( var->data.original.transvar == NULL )
15998  return 0;
15999  else
16001 
16002  case SCIP_VARSTATUS_LOOSE:
16003  case SCIP_VARSTATUS_COLUMN:
16004  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
16005 
16006  case SCIP_VARSTATUS_FIXED:
16007  return 0;
16008 
16010  if( var->data.aggregate.scalar > 0.0 )
16011  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
16012  else
16014 
16016  return 0;
16017 
16020 
16021  default:
16022  SCIPerrorMessage("unknown variable status\n");
16023  SCIPABORT();
16024  return 0; /*lint !e527*/
16025  }
16026 }
16027 
16028 /** returns the average number of cutoffs found after branching on the variable in given direction */
16030  SCIP_VAR* var, /**< problem variable */
16031  SCIP_STAT* stat, /**< problem statistics */
16032  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16033  )
16034 {
16035  assert(var != NULL);
16036  assert(stat != NULL);
16037  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16038 
16039  switch( SCIPvarGetStatus(var) )
16040  {
16042  if( var->data.original.transvar == NULL )
16043  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16044  else
16045  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
16046 
16047  case SCIP_VARSTATUS_LOOSE:
16048  case SCIP_VARSTATUS_COLUMN:
16049  return SCIPhistoryGetNBranchings(var->history, dir) > 0
16050  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
16051  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
16052 
16053  case SCIP_VARSTATUS_FIXED:
16054  return 0.0;
16055 
16057  if( var->data.aggregate.scalar > 0.0 )
16058  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
16059  else
16060  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
16061 
16063  return 0.0;
16064 
16066  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
16067 
16068  default:
16069  SCIPerrorMessage("unknown variable status\n");
16070  SCIPABORT();
16071  return 0.0; /*lint !e527*/
16072  }
16073 }
16074 
16075 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
16077  SCIP_VAR* var, /**< problem variable */
16078  SCIP_STAT* stat, /**< problem statistics */
16079  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
16080  )
16081 {
16082  assert(var != NULL);
16083  assert(stat != NULL);
16084  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
16085 
16086  switch( SCIPvarGetStatus(var) )
16087  {
16089  if( var->data.original.transvar == NULL )
16090  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
16091  else
16092  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
16093 
16094  case SCIP_VARSTATUS_LOOSE:
16095  case SCIP_VARSTATUS_COLUMN:
16096  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
16099 
16100  case SCIP_VARSTATUS_FIXED:
16101  return 0.0;
16102 
16104  if( var->data.aggregate.scalar > 0.0 )
16105  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
16106  else
16108 
16110  return 0.0;
16111 
16114 
16115  default:
16116  SCIPerrorMessage("unknown variable status\n");
16117  SCIPABORT();
16118  return 0.0; /*lint !e527*/
16119  }
16120 }
16121 
16122 
16123 
16124 
16125 /*
16126  * information methods for bound changes
16127  */
16128 
16129 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
16131  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16132  BMS_BLKMEM* blkmem, /**< block memory */
16133  SCIP_VAR* var, /**< active variable that changed the bounds */
16134  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
16135  SCIP_Real oldbound, /**< old value for bound */
16136  SCIP_Real newbound /**< new value for bound */
16137  )
16138 {
16139  assert(bdchginfo != NULL);
16140 
16141  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
16142  (*bdchginfo)->oldbound = oldbound;
16143  (*bdchginfo)->newbound = newbound;
16144  (*bdchginfo)->var = var;
16145  (*bdchginfo)->inferencedata.var = var;
16146  (*bdchginfo)->inferencedata.reason.prop = NULL;
16147  (*bdchginfo)->inferencedata.info = 0;
16148  (*bdchginfo)->bdchgidx.depth = INT_MAX;
16149  (*bdchginfo)->bdchgidx.pos = -1;
16150  (*bdchginfo)->pos = 0;
16151  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
16152  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
16153  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
16154  (*bdchginfo)->redundant = FALSE;
16155 
16156  return SCIP_OKAY;
16157 }
16158 
16159 /** frees a bound change information object */
16160 void SCIPbdchginfoFree(
16161  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
16162  BMS_BLKMEM* blkmem /**< block memory */
16163  )
16164 {
16165  assert(bdchginfo != NULL);
16166 
16167  BMSfreeBlockMemory(blkmem, bdchginfo);
16168 }
16169 
16170 /** returns the bound change information for the last lower bound change on given active problem variable before or
16171  * after the bound change with the given index was applied;
16172  * returns NULL, if no change to the lower bound was applied up to this point of time
16173  */
16175  SCIP_VAR* var, /**< active problem variable */
16176  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16177  SCIP_Bool after /**< should the bound change with given index be included? */
16178  )
16179 {
16180  int i;
16181 
16182  assert(var != NULL);
16183  assert(SCIPvarIsActive(var));
16184 
16185  /* search the correct bound change information for the given bound change index */
16186  if( after )
16187  {
16188  for( i = var->nlbchginfos-1; i >= 0; --i )
16189  {
16190  assert(var->lbchginfos[i].var == var);
16192  assert(var->lbchginfos[i].pos == i);
16193 
16194  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16195  if( var->lbchginfos[i].redundant )
16196  return NULL;
16197  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16198 
16199  /* if we reached the bound change index, return the current bound change info */
16200  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
16201  return &var->lbchginfos[i];
16202  }
16203  }
16204  else
16205  {
16206  for( i = var->nlbchginfos-1; i >= 0; --i )
16207  {
16208  assert(var->lbchginfos[i].var == var);
16210  assert(var->lbchginfos[i].pos == i);
16211 
16212  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16213  if( var->lbchginfos[i].redundant )
16214  return NULL;
16215  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
16216 
16217  /* if we reached the bound change index, return the current bound change info */
16218  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
16219  return &var->lbchginfos[i];
16220  }
16221  }
16222 
16223  return NULL;
16224 }
16225 
16226 /** returns the bound change information for the last upper bound change on given active problem variable before or
16227  * after the bound change with the given index was applied;
16228  * returns NULL, if no change to the upper bound was applied up to this point of time
16229  */
16231  SCIP_VAR* var, /**< active problem variable */
16232  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16233  SCIP_Bool after /**< should the bound change with given index be included? */
16234  )
16235 {
16236  int i;
16237 
16238  assert(var != NULL);
16239  assert(SCIPvarIsActive(var));
16240 
16241  /* search the correct bound change information for the given bound change index */
16242  if( after )
16243  {
16244  for( i = var->nubchginfos-1; i >= 0; --i )
16245  {
16246  assert(var->ubchginfos[i].var == var);
16248  assert(var->ubchginfos[i].pos == i);
16249 
16250  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16251  if( var->ubchginfos[i].redundant )
16252  return NULL;
16253  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16254 
16255  /* if we reached the bound change index, return the current bound change info */
16256  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
16257  return &var->ubchginfos[i];
16258  }
16259  }
16260  else
16261  {
16262  for( i = var->nubchginfos-1; i >= 0; --i )
16263  {
16264  assert(var->ubchginfos[i].var == var);
16266  assert(var->ubchginfos[i].pos == i);
16267 
16268  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
16269  if( var->ubchginfos[i].redundant )
16270  return NULL;
16271  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
16272 
16273  /* if we reached the bound change index, return the current bound change info */
16274  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
16275  return &var->ubchginfos[i];
16276  }
16277  }
16278 
16279  return NULL;
16280 }
16281 
16282 /** returns the bound change information for the last lower or upper bound change on given active problem variable
16283  * before or after the bound change with the given index was applied;
16284  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
16285  */
16287  SCIP_VAR* var, /**< active problem variable */
16288  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16289  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16290  SCIP_Bool after /**< should the bound change with given index be included? */
16291  )
16292 {
16293  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16294  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
16295  else
16296  {
16297  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16298  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
16299  }
16300 }
16301 
16302 /** returns lower bound of variable directly before or after the bound change given by the bound change index
16303  * was applied
16304  *
16305  * @deprecated Please use SCIPgetVarLbAtIndex()
16306  */
16308  SCIP_VAR* var, /**< problem variable */
16309  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16310  SCIP_Bool after /**< should the bound change with given index be included? */
16311  )
16312 {
16313  SCIP_VARSTATUS varstatus;
16314  assert(var != NULL);
16315 
16316  varstatus = SCIPvarGetStatus(var);
16317 
16318  /* get bounds of attached variables */
16319  switch( varstatus )
16320  {
16322  assert(var->data.original.transvar != NULL);
16323  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
16324 
16325  case SCIP_VARSTATUS_LOOSE:
16326  case SCIP_VARSTATUS_COLUMN:
16327  if( bdchgidx == NULL )
16328  return SCIPvarGetLbLocal(var);
16329  else
16330  {
16331  SCIP_BDCHGINFO* bdchginfo;
16332 
16333  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
16334  if( bdchginfo != NULL )
16335  return SCIPbdchginfoGetNewbound(bdchginfo);
16336  else
16337  return var->glbdom.lb;
16338  }
16339  case SCIP_VARSTATUS_FIXED:
16340  return var->glbdom.lb;
16341 
16342  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16343  assert(var->data.aggregate.var != NULL);
16344  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16345  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16346  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16347  * (or is called by) a public interface method; instead, we only assert that values are finite
16348  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16349  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16350  */
16351  if( var->data.aggregate.scalar > 0.0 )
16352  {
16353  /* a > 0 -> get lower bound of y */
16354  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16355  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16356  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16357  + var->data.aggregate.constant;
16358  }
16359  else if( var->data.aggregate.scalar < 0.0 )
16360  {
16361  /* a < 0 -> get upper bound of y */
16362  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16363  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16364  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16365  + var->data.aggregate.constant;
16366  }
16367  else
16368  {
16369  SCIPerrorMessage("scalar is zero in aggregation\n");
16370  SCIPABORT();
16371  return SCIP_INVALID; /*lint !e527*/
16372  }
16373 
16375  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16376  if ( var->data.multaggr.nvars == 1 )
16377  {
16378  assert(var->data.multaggr.vars != NULL);
16379  assert(var->data.multaggr.scalars != NULL);
16380  assert(var->data.multaggr.vars[0] != NULL);
16381 
16382  if( var->data.multaggr.scalars[0] > 0.0 )
16383  {
16384  /* a > 0 -> get lower bound of y */
16385  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16386  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16387  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16388  + var->data.multaggr.constant;
16389  }
16390  else if( var->data.multaggr.scalars[0] < 0.0 )
16391  {
16392  /* a < 0 -> get upper bound of y */
16393  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16394  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16395  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16396  + var->data.multaggr.constant;
16397  }
16398  else
16399  {
16400  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16401  SCIPABORT();
16402  return SCIP_INVALID; /*lint !e527*/
16403  }
16404  }
16405  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16406  SCIPABORT();
16407  return SCIP_INVALID; /*lint !e527*/
16408 
16409  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16410  assert(var->negatedvar != NULL);
16412  assert(var->negatedvar->negatedvar == var);
16413  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16414  default:
16415  SCIPerrorMessage("unknown variable status\n");
16416  SCIPABORT();
16417  return SCIP_INVALID; /*lint !e527*/
16418  }
16419 }
16420 
16421 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16422  * was applied
16423  *
16424  * @deprecated Please use SCIPgetVarUbAtIndex()
16425  */
16427  SCIP_VAR* var, /**< problem variable */
16428  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16429  SCIP_Bool after /**< should the bound change with given index be included? */
16430  )
16431 {
16432  SCIP_VARSTATUS varstatus;
16433  assert(var != NULL);
16434 
16435  varstatus = SCIPvarGetStatus(var);
16436 
16437  /* get bounds of attached variables */
16438  switch( varstatus )
16439  {
16441  assert(var->data.original.transvar != NULL);
16442  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16443 
16444  case SCIP_VARSTATUS_COLUMN:
16445  case SCIP_VARSTATUS_LOOSE:
16446  if( bdchgidx == NULL )
16447  return SCIPvarGetUbLocal(var);
16448  else
16449  {
16450  SCIP_BDCHGINFO* bdchginfo;
16451 
16452  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16453  if( bdchginfo != NULL )
16454  return SCIPbdchginfoGetNewbound(bdchginfo);
16455  else
16456  return var->glbdom.ub;
16457  }
16458 
16459  case SCIP_VARSTATUS_FIXED:
16460  return var->glbdom.ub;
16461 
16462  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16463  assert(var->data.aggregate.var != NULL);
16464  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16465  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16466  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16467  * (or is called by) a public interface method; instead, we only assert that values are finite
16468  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16469  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16470  */
16471  if( var->data.aggregate.scalar > 0.0 )
16472  {
16473  /* a > 0 -> get lower bound of y */
16474  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16475  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16476  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16477  + var->data.aggregate.constant;
16478  }
16479  else if( var->data.aggregate.scalar < 0.0 )
16480  {
16481  /* a < 0 -> get upper bound of y */
16482  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16483  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16484  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16485  + var->data.aggregate.constant;
16486  }
16487  else
16488  {
16489  SCIPerrorMessage("scalar is zero in aggregation\n");
16490  SCIPABORT();
16491  return SCIP_INVALID; /*lint !e527*/
16492  }
16493 
16495  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16496  if ( var->data.multaggr.nvars == 1 )
16497  {
16498  assert(var->data.multaggr.vars != NULL);
16499  assert(var->data.multaggr.scalars != NULL);
16500  assert(var->data.multaggr.vars[0] != NULL);
16501 
16502  if( var->data.multaggr.scalars[0] > 0.0 )
16503  {
16504  /* a > 0 -> get lower bound of y */
16505  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16506  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16507  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16508  + var->data.multaggr.constant;
16509  }
16510  else if( var->data.multaggr.scalars[0] < 0.0 )
16511  {
16512  /* a < 0 -> get upper bound of y */
16513  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16514  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16515  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16516  + var->data.multaggr.constant;
16517  }
16518  else
16519  {
16520  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16521  SCIPABORT();
16522  return SCIP_INVALID; /*lint !e527*/
16523  }
16524  }
16525  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16526  SCIPABORT();
16527  return SCIP_INVALID; /*lint !e527*/
16528 
16529  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16530  assert(var->negatedvar != NULL);
16532  assert(var->negatedvar->negatedvar == var);
16533  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16534 
16535  default:
16536  SCIPerrorMessage("unknown variable status\n");
16537  SCIPABORT();
16538  return SCIP_INVALID; /*lint !e527*/
16539  }
16540 }
16541 
16542 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16543  * was applied
16544  *
16545  * @deprecated Please use SCIPgetVarBdAtIndex()
16546  */
16548  SCIP_VAR* var, /**< problem variable */
16549  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16550  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16551  SCIP_Bool after /**< should the bound change with given index be included? */
16552  )
16553 {
16554  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16555  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16556  else
16557  {
16558  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16559  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16560  }
16561 }
16562 
16563 /** returns whether the binary variable was fixed at the time given by the bound change index
16564  *
16565  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16566  */
16568  SCIP_VAR* var, /**< problem variable */
16569  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16570  SCIP_Bool after /**< should the bound change with given index be included? */
16571  )
16572 {
16573  assert(var != NULL);
16574  assert(SCIPvarIsBinary(var));
16575 
16576  /* check the current bounds first in order to decide at which bound change information we have to look
16577  * (which is expensive because we have to follow the aggregation tree to the active variable)
16578  */
16579  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16580  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16581 }
16582 
16583 /** bound change index representing the initial time before any bound changes took place */
16584 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16586 /** bound change index representing the presolving stage */
16587 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16589 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16591  SCIP_VAR* var /**< problem variable */
16592  )
16593 {
16594  SCIP_BDCHGIDX* lbchgidx;
16595  SCIP_BDCHGIDX* ubchgidx;
16596 
16597  assert(var != NULL);
16598 
16599  var = SCIPvarGetProbvar(var);
16600 
16601  /* check, if variable is original without transformed variable */
16602  if( var == NULL )
16603  return &initbdchgidx;
16604 
16605  /* check, if variable was fixed in presolving */
16606  if( !SCIPvarIsActive(var) )
16607  return &presolvebdchgidx;
16608 
16610 
16611  /* get depths of last bound change information for the lower and upper bound */
16612  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16613  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16614  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16615  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16616 
16617  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16618  return ubchgidx;
16619  else
16620  return lbchgidx;
16621 }
16622 
16623 /** returns the last depth level, at which the bounds of the given variable were tightened;
16624  * returns -2, if the variable's bounds are still the global bounds
16625  * returns -1, if the variable was fixed in presolving
16626  */
16628  SCIP_VAR* var /**< problem variable */
16629  )
16630 {
16631  SCIP_BDCHGIDX* bdchgidx;
16632 
16633  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16634  assert(bdchgidx != NULL);
16635 
16636  return bdchgidx->depth;
16637 }
16638 
16639 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16640  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16641  */
16643  SCIP_VAR* var, /**< problem variable */
16644  SCIP_SET* set, /**< global SCIP settings */
16645  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16646  SCIP_Real bound /**< conflicting bound */
16647  )
16648 {
16649  int i;
16650 
16651  assert(var != NULL);
16652  assert(set != NULL);
16653  assert(var->scip == set->scip);
16654 
16655  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16656  {
16657  /* check if the bound is in conflict with the current local bounds */
16658  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16659  return -1;
16660 
16661  /* check if the bound is in conflict with the global bound */
16662  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16663  return 0;
16664 
16665  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16666  assert(var->nubchginfos > 0);
16667  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16668 
16669  /* search for the first conflicting bound change */
16670  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16671  {
16672  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16674  }
16675  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16676  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16677 
16678  /* return the depth at which the first conflicting bound change took place */
16679  return var->ubchginfos[i].bdchgidx.depth;
16680  }
16681  else
16682  {
16683  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16684 
16685  /* check if the bound is in conflict with the current local bounds */
16686  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16687  return -1;
16688 
16689  /* check if the bound is in conflict with the global bound */
16690  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16691  return 0;
16692 
16693  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16694  assert(var->nlbchginfos > 0);
16695  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16696 
16697  /* search for the first conflicting bound change */
16698  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16699  {
16700  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16702  }
16703  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16704  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16705 
16706  /* return the depth at which the first conflicting bound change took place */
16707  return var->lbchginfos[i].bdchgidx.depth;
16708  }
16709 }
16710 
16711 /** returns whether the first binary variable was fixed earlier than the second one;
16712  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16713  * second one is not fixed
16714  */
16716  SCIP_VAR* var1, /**< first binary variable */
16717  SCIP_VAR* var2 /**< second binary variable */
16718  )
16719 {
16720  SCIP_BDCHGIDX* bdchgidx1;
16721  SCIP_BDCHGIDX* bdchgidx2;
16722 
16723  assert(var1 != NULL);
16724  assert(var2 != NULL);
16725  assert(SCIPvarIsBinary(var1));
16726  assert(SCIPvarIsBinary(var2));
16727 
16728  var1 = SCIPvarGetProbvar(var1);
16729  var2 = SCIPvarGetProbvar(var2);
16730  assert(var1 != NULL);
16731  assert(var2 != NULL);
16732 
16733  /* check, if variables are globally fixed */
16734  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16735  return FALSE;
16736  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16737  return TRUE;
16738 
16741  assert(SCIPvarIsBinary(var1));
16742  assert(SCIPvarIsBinary(var2));
16743  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16744  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16745  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16746  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16747  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16748  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16749 
16750  if( var1->nlbchginfos == 1 )
16751  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16752  else if( var1->nubchginfos == 1 )
16753  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16754  else
16755  bdchgidx1 = NULL;
16756 
16757  if( var2->nlbchginfos == 1 )
16758  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16759  else if( var2->nubchginfos == 1 )
16760  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16761  else
16762  bdchgidx2 = NULL;
16763 
16764  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16765 }
16766 
16767 
16768 
16769 /*
16770  * Hash functions
16771  */
16772 
16773 /** gets the key (i.e. the name) of the given variable */
16774 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16775 { /*lint --e{715}*/
16776  SCIP_VAR* var = (SCIP_VAR*)elem;
16777 
16778  assert(var != NULL);
16779  return var->name;
16780 }
16781 
16782 
16783 
16784 
16785 /*
16786  * simple functions implemented as defines
16787  */
16788 
16789 /* In debug mode, the following methods are implemented as function calls to ensure
16790  * type validity.
16791  * In optimized mode, the methods are implemented as defines to improve performance.
16792  * However, we want to have them in the library anyways, so we have to undef the defines.
16793  */
16794 
16795 #undef SCIPboundchgGetNewbound
16796 #undef SCIPboundchgGetVar
16797 #undef SCIPboundchgGetBoundchgtype
16798 #undef SCIPboundchgGetBoundtype
16799 #undef SCIPboundchgIsRedundant
16800 #undef SCIPdomchgGetNBoundchgs
16801 #undef SCIPdomchgGetBoundchg
16802 #undef SCIPholelistGetLeft
16803 #undef SCIPholelistGetRight
16804 #undef SCIPholelistGetNext
16805 #undef SCIPvarGetName
16806 #undef SCIPvarGetNUses
16807 #undef SCIPvarGetData
16808 #undef SCIPvarSetData
16809 #undef SCIPvarSetDelorigData
16810 #undef SCIPvarSetTransData
16811 #undef SCIPvarSetDeltransData
16812 #undef SCIPvarGetStatus
16813 #undef SCIPvarIsOriginal
16814 #undef SCIPvarIsTransformed
16815 #undef SCIPvarIsNegated
16816 #undef SCIPvarGetType
16817 #undef SCIPvarIsBinary
16818 #undef SCIPvarIsIntegral
16819 #undef SCIPvarIsInitial
16820 #undef SCIPvarIsRemovable
16821 #undef SCIPvarIsDeleted
16822 #undef SCIPvarIsDeletable
16823 #undef SCIPvarMarkDeletable
16824 #undef SCIPvarMarkNotDeletable
16825 #undef SCIPvarIsActive
16826 #undef SCIPvarGetIndex
16827 #undef SCIPvarGetProbindex
16828 #undef SCIPvarGetTransVar
16829 #undef SCIPvarGetCol
16830 #undef SCIPvarIsInLP
16831 #undef SCIPvarGetAggrVar
16832 #undef SCIPvarGetAggrScalar
16833 #undef SCIPvarGetAggrConstant
16834 #undef SCIPvarGetMultaggrNVars
16835 #undef SCIPvarGetMultaggrVars
16836 #undef SCIPvarGetMultaggrScalars
16837 #undef SCIPvarGetMultaggrConstant
16838 #undef SCIPvarGetNegatedVar
16839 #undef SCIPvarGetNegationVar
16840 #undef SCIPvarGetNegationConstant
16841 #undef SCIPvarGetObj
16842 #undef SCIPvarGetLbOriginal
16843 #undef SCIPvarGetUbOriginal
16844 #undef SCIPvarGetHolelistOriginal
16845 #undef SCIPvarGetLbGlobal
16846 #undef SCIPvarGetUbGlobal
16847 #undef SCIPvarGetHolelistGlobal
16848 #undef SCIPvarGetBestBoundGlobal
16849 #undef SCIPvarGetWorstBoundGlobal
16850 #undef SCIPvarGetLbLocal
16851 #undef SCIPvarGetUbLocal
16852 #undef SCIPvarGetHolelistLocal
16853 #undef SCIPvarGetBestBoundLocal
16854 #undef SCIPvarGetWorstBoundLocal
16855 #undef SCIPvarGetBestBoundType
16856 #undef SCIPvarGetWorstBoundType
16857 #undef SCIPvarGetLbLazy
16858 #undef SCIPvarGetUbLazy
16859 #undef SCIPvarGetBranchFactor
16860 #undef SCIPvarGetBranchPriority
16861 #undef SCIPvarGetBranchDirection
16862 #undef SCIPvarGetNVlbs
16863 #undef SCIPvarGetVlbVars
16864 #undef SCIPvarGetVlbCoefs
16865 #undef SCIPvarGetVlbConstants
16866 #undef SCIPvarGetNVubs
16867 #undef SCIPvarGetVubVars
16868 #undef SCIPvarGetVubCoefs
16869 #undef SCIPvarGetVubConstants
16870 #undef SCIPvarGetNImpls
16871 #undef SCIPvarGetImplVars
16872 #undef SCIPvarGetImplTypes
16873 #undef SCIPvarGetImplBounds
16874 #undef SCIPvarGetImplIds
16875 #undef SCIPvarGetNCliques
16876 #undef SCIPvarGetCliques
16877 #undef SCIPvarGetLPSol
16878 #undef SCIPvarGetNLPSol
16879 #undef SCIPvarGetBdchgInfoLb
16880 #undef SCIPvarGetNBdchgInfosLb
16881 #undef SCIPvarGetBdchgInfoUb
16882 #undef SCIPvarGetNBdchgInfosUb
16883 #undef SCIPvarGetValuehistory
16884 #undef SCIPvarGetPseudoSol
16885 #undef SCIPvarCatchEvent
16886 #undef SCIPvarDropEvent
16887 #undef SCIPvarGetVSIDS
16888 #undef SCIPvarGetCliqueComponentIdx
16889 #undef SCIPvarIsRelaxationOnly
16890 #undef SCIPvarMarkRelaxationOnly
16891 #undef SCIPbdchgidxGetPos
16892 #undef SCIPbdchgidxIsEarlierNonNull
16893 #undef SCIPbdchgidxIsEarlier
16894 #undef SCIPbdchginfoGetOldbound
16895 #undef SCIPbdchginfoGetNewbound
16896 #undef SCIPbdchginfoGetVar
16897 #undef SCIPbdchginfoGetChgtype
16898 #undef SCIPbdchginfoGetBoundtype
16899 #undef SCIPbdchginfoGetDepth
16900 #undef SCIPbdchginfoGetPos
16901 #undef SCIPbdchginfoGetIdx
16902 #undef SCIPbdchginfoGetInferVar
16903 #undef SCIPbdchginfoGetInferCons
16904 #undef SCIPbdchginfoGetInferProp
16905 #undef SCIPbdchginfoGetInferInfo
16906 #undef SCIPbdchginfoGetInferBoundtype
16907 #undef SCIPbdchginfoIsRedundant
16908 #undef SCIPbdchginfoHasInferenceReason
16909 #undef SCIPbdchginfoIsTighter
16910 
16911 
16912 /** returns the new value of the bound in the bound change data */
16914  SCIP_BOUNDCHG* boundchg /**< bound change data */
16915  )
16916 {
16917  assert(boundchg != NULL);
16918 
16919  return boundchg->newbound;
16920 }
16921 
16922 /** returns the variable of the bound change in the bound change data */
16924  SCIP_BOUNDCHG* boundchg /**< bound change data */
16925  )
16926 {
16927  assert(boundchg != NULL);
16928 
16929  return boundchg->var;
16930 }
16931 
16932 /** returns the bound change type of the bound change in the bound change data */
16934  SCIP_BOUNDCHG* boundchg /**< bound change data */
16935  )
16936 {
16937  assert(boundchg != NULL);
16938 
16939  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16940 }
16941 
16942 /** returns the bound type of the bound change in the bound change data */
16944  SCIP_BOUNDCHG* boundchg /**< bound change data */
16945  )
16946 {
16947  assert(boundchg != NULL);
16948 
16949  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16950 }
16951 
16952 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16954  SCIP_BOUNDCHG* boundchg /**< bound change data */
16955  )
16956 {
16957  assert(boundchg != NULL);
16958 
16959  return boundchg->redundant;
16960 }
16961 
16962 /** returns the number of bound changes in the domain change data */
16964  SCIP_DOMCHG* domchg /**< domain change data */
16965  )
16966 {
16967  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16968 }
16969 
16970 /** returns a particular bound change in the domain change data */
16972  SCIP_DOMCHG* domchg, /**< domain change data */
16973  int pos /**< position of the bound change in the domain change data */
16974  )
16975 {
16976  assert(domchg != NULL);
16977  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16978 
16979  return &domchg->domchgbound.boundchgs[pos];
16980 }
16981 
16982 /** returns left bound of open interval in hole */
16984  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16985  )
16986 {
16987  assert(holelist != NULL);
16988 
16989  return holelist->hole.left;
16990 }
16991 
16992 /** returns right bound of open interval in hole */
16994  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16995  )
16996 {
16997  assert(holelist != NULL);
16998 
16999  return holelist->hole.right;
17000 }
17001 
17002 /** returns next hole in list */
17004  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
17005  )
17006 {
17007  assert(holelist != NULL);
17008 
17009  return holelist->next;
17010 }
17011 
17012 /** returns the name of the variable
17013  *
17014  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
17015  */
17016 const char* SCIPvarGetName(
17017  SCIP_VAR* var /**< problem variable */
17018  )
17019 {
17020  assert(var != NULL);
17021 
17022  return var->name;
17023 }
17024 
17025 /** gets number of times, the variable is currently captured */
17026 int SCIPvarGetNUses(
17027  SCIP_VAR* var /**< problem variable */
17028  )
17029 {
17030  assert(var != NULL);
17031 
17032  return var->nuses;
17033 }
17034 
17035 /** returns the user data of the variable */
17037  SCIP_VAR* var /**< problem variable */
17038  )
17039 {
17040  assert(var != NULL);
17041 
17042  return var->vardata;
17043 }
17044 
17045 /** sets the user data for the variable */
17046 void SCIPvarSetData(
17047  SCIP_VAR* var, /**< problem variable */
17048  SCIP_VARDATA* vardata /**< user variable data */
17049  )
17050 {
17051  assert(var != NULL);
17052 
17053  var->vardata = vardata;
17054 }
17055 
17056 /** sets method to free user data for the original variable */
17058  SCIP_VAR* var, /**< problem variable */
17059  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
17060  )
17061 {
17062  assert(var != NULL);
17063  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17064 
17065  var->vardelorig = vardelorig;
17066 }
17067 
17068 /** sets method to transform user data of the variable */
17069 void SCIPvarSetTransData(
17070  SCIP_VAR* var, /**< problem variable */
17071  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
17072  )
17073 {
17074  assert(var != NULL);
17075  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17076 
17077  var->vartrans = vartrans;
17078 }
17079 
17080 /** sets method to free transformed user data for the variable */
17082  SCIP_VAR* var, /**< problem variable */
17083  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
17084  )
17085 {
17086  assert(var != NULL);
17087 
17088  var->vardeltrans = vardeltrans;
17089 }
17090 
17091 /** sets method to copy this variable into sub-SCIPs */
17092 void SCIPvarSetCopyData(
17093  SCIP_VAR* var, /**< problem variable */
17094  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
17095  )
17096 {
17097  assert(var != NULL);
17098 
17099  var->varcopy = varcopy;
17100 }
17101 
17102 /** sets the initial flag of a variable; only possible for original or loose variables */
17104  SCIP_VAR* var, /**< problem variable */
17105  SCIP_Bool initial /**< initial flag */
17106  )
17107 {
17108  assert(var != NULL);
17109 
17111  return SCIP_INVALIDCALL;
17112 
17113  var->initial = initial;
17114 
17115  return SCIP_OKAY;
17116 }
17117 
17118 /** sets the removable flag of a variable; only possible for original or loose variables */
17120  SCIP_VAR* var, /**< problem variable */
17121  SCIP_Bool removable /**< removable flag */
17122  )
17123 {
17124  assert(var != NULL);
17125 
17127  return SCIP_INVALIDCALL;
17128 
17129  var->removable = removable;
17130 
17131  return SCIP_OKAY;
17132 }
17133 
17134 /** gets status of variable */
17136  SCIP_VAR* var /**< problem variable */
17137  )
17138 {
17139  assert(var != NULL);
17140 
17141  return (SCIP_VARSTATUS)(var->varstatus);
17142 }
17143 
17144 /** returns whether the variable belongs to the original problem */
17146  SCIP_VAR* var /**< problem variable */
17147  )
17148 {
17149  assert(var != NULL);
17150  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17151 
17155 }
17156 
17157 /** returns whether the variable belongs to the transformed problem */
17159  SCIP_VAR* var /**< problem variable */
17160  )
17161 {
17162  assert(var != NULL);
17163  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
17164 
17168 }
17169 
17170 /** returns whether the variable was created by negation of a different variable */
17172  SCIP_VAR* var /**< problem variable */
17173  )
17174 {
17175  assert(var != NULL);
17176 
17177  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17178 }
17179 
17180 /** gets type of variable */
17182  SCIP_VAR* var /**< problem variable */
17183  )
17184 {
17185  assert(var != NULL);
17186 
17187  return (SCIP_VARTYPE)(var->vartype);
17188 }
17189 
17190 /** returns TRUE if the variable is of binary type; this is the case if:
17191  * (1) variable type is binary
17192  * (2) variable type is integer or implicit integer and
17193  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
17194  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
17195  */
17197  SCIP_VAR* var /**< problem variable */
17198  )
17199 {
17200  assert(var != NULL);
17201 
17202  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
17203  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
17204 }
17205 
17206 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
17208  SCIP_VAR* var /**< problem variable */
17209  )
17210 {
17211  assert(var != NULL);
17212 
17213  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
17214 }
17215 
17216 /** returns whether variable's column should be present in the initial root LP */
17218  SCIP_VAR* var /**< problem variable */
17219  )
17220 {
17221  assert(var != NULL);
17222 
17223  return var->initial;
17224 }
17225 
17226 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
17228  SCIP_VAR* var /**< problem variable */
17229  )
17230 {
17231  assert(var != NULL);
17232 
17233  return var->removable;
17234 }
17235 
17236 /** returns whether the variable was deleted from the problem */
17238  SCIP_VAR* var /**< problem variable */
17239  )
17240 {
17241  assert(var != NULL);
17242 
17243  return var->deleted;
17244 }
17245 
17246 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
17247  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
17248  */
17250  SCIP_VAR* var /**< problem variable */
17251  )
17252 {
17253  assert(var != NULL);
17254  assert(var->probindex == -1);
17255 
17256  var->deletable = TRUE;
17257 }
17258 
17259 /** marks the variable to be not deletable from the problem */
17262  )
17263 {
17264  assert(var != NULL);
17265 
17266  var->deletable = FALSE;
17267 }
17268 
17269 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
17270  *
17271  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
17272  */
17274  SCIP_VAR* var /**< problem variable */
17275  )
17276 {
17277  assert(var != NULL);
17278 
17279  var->delglobalstructs = TRUE;
17280 }
17281 
17282 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
17284  SCIP_VAR* var /**< problem variable */
17285  )
17286 {
17287  assert(var != NULL);
17288 
17289  return var->delglobalstructs;
17290 }
17291 
17292 /** returns whether a variable has been introduced to define a relaxation
17293  *
17294  * These variables are only valid for the current SCIP solve round,
17295  * they are not contained in any (checked) constraints, but may be used
17296  * in cutting planes, for example.
17297  * Relaxation-only variables are not copied by SCIPcopyVars and cuts
17298  * that contain these variables are not added as linear constraints when
17299  * restarting or transferring information from a copied SCIP to a SCIP.
17300  * Also conflicts with relaxation-only variables are not generated at
17301  * the moment.
17302  */
17304  SCIP_VAR* var /**< problem variable */
17305  )
17306 {
17307  assert(var != NULL);
17308 
17309  return var->relaxationonly;
17310 }
17311 
17312 /** marks that this variable has only been introduced to define a relaxation
17313  *
17314  * The variable must not have a coefficient in the objective.
17315  *
17316  * @see SCIPvarIsRelaxationOnly
17317  */
17319  SCIP_VAR* var /**< problem variable */
17320  )
17321 {
17322  assert(var != NULL);
17323  assert(SCIPvarGetObj(var) == 0.0);
17324 
17325  var->relaxationonly = TRUE;
17326 }
17327 
17328 /** returns whether variable is allowed to be deleted completely from the problem */
17331  )
17332 {
17333  assert(var != NULL);
17334 
17335  return var->deletable;
17336 }
17337 
17338 /** returns whether variable is an active (neither fixed nor aggregated) variable */
17340  SCIP_VAR* var /**< problem variable */
17341  )
17342 {
17343  assert(var != NULL);
17344 
17345  return (var->probindex >= 0);
17346 }
17347 
17348 /** gets unique index of variable */
17349 int SCIPvarGetIndex(
17350  SCIP_VAR* var /**< problem variable */
17351  )
17352 {
17353  assert(var != NULL);
17354 
17355  return var->index;
17356 }
17357 
17358 /** gets position of variable in problem, or -1 if variable is not active */
17360  SCIP_VAR* var /**< problem variable */
17361  )
17362 {
17363  assert(var != NULL);
17364 
17365  return var->probindex;
17366 }
17367 
17368 /** gets transformed variable of ORIGINAL variable */
17370  SCIP_VAR* var /**< problem variable */
17371  )
17372 {
17373  assert(var != NULL);
17374  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
17375 
17376  return var->data.original.transvar;
17377 }
17378 
17379 /** gets column of COLUMN variable */
17381  SCIP_VAR* var /**< problem variable */
17382  )
17383 {
17384  assert(var != NULL);
17385  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
17386 
17387  return var->data.col;
17388 }
17389 
17390 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17392  SCIP_VAR* var /**< problem variable */
17393  )
17394 {
17395  assert(var != NULL);
17396 
17397  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17398 }
17399 
17400 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17402  SCIP_VAR* var /**< problem variable */
17403  )
17404 {
17405  assert(var != NULL);
17407 
17408  return var->data.aggregate.var;
17409 }
17410 
17411 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17413  SCIP_VAR* var /**< problem variable */
17414  )
17415 {
17416  assert(var != NULL);
17418 
17419  return var->data.aggregate.scalar;
17420 }
17421 
17422 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17424  SCIP_VAR* var /**< problem variable */
17425  )
17426 {
17427  assert(var != NULL);
17429 
17430  return var->data.aggregate.constant;
17431 }
17432 
17433 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17435  SCIP_VAR* var /**< problem variable */
17436  )
17437 {
17438  assert(var != NULL);
17439  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17440  assert(!var->donotmultaggr);
17441 
17442  return var->data.multaggr.nvars;
17443 }
17444 
17445 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17447  SCIP_VAR* var /**< problem variable */
17448  )
17449 {
17450  assert(var != NULL);
17451  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17452  assert(!var->donotmultaggr);
17453 
17454  return var->data.multaggr.vars;
17455 }
17456 
17457 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17459  SCIP_VAR* var /**< problem variable */
17460  )
17461 {
17462  assert(var != NULL);
17463  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17464  assert(!var->donotmultaggr);
17465 
17466  return var->data.multaggr.scalars;
17467 }
17468 
17469 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17471  SCIP_VAR* var /**< problem variable */
17472  )
17473 {
17474  assert(var != NULL);
17475  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17476  assert(!var->donotmultaggr);
17477 
17478  return var->data.multaggr.constant;
17479 }
17480 
17481 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17483  SCIP_VAR* var /**< negated problem variable */
17484  )
17485 {
17486  assert(var != NULL);
17487 
17488  return var->negatedvar;
17489 }
17490 
17491 /** gets the negation variable x of a negated variable x' = offset - x */
17493  SCIP_VAR* var /**< negated problem variable */
17494  )
17495 {
17496  assert(var != NULL);
17497  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17498 
17499  return var->negatedvar;
17500 }
17501 
17502 /** gets the negation offset of a negated variable x' = offset - x */
17504  SCIP_VAR* var /**< negated problem variable */
17505  )
17506 {
17507  assert(var != NULL);
17508  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17509 
17510  return var->data.negate.constant;
17511 }
17512 
17513 /** gets objective function value of variable */
17515  SCIP_VAR* var /**< problem variable */
17516  )
17517 {
17518  assert(var != NULL);
17519 
17520  return var->obj;
17521 }
17522 
17523 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17525  SCIP_VAR* var /**< problem variable */
17526  )
17527 {
17528  assert(var != NULL);
17529 
17530  return var->unchangedobj;
17531 }
17532 
17533 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17534  * e.g. obj(x) = 1 this method returns for ~x the value -1
17535  */
17537  SCIP_VAR* var, /**< problem variable */
17538  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17539  )
17540 {
17541  SCIP_VAR* probvar = var;
17542  SCIP_Real mult = 1.0;
17543 
17544  assert(probvar != NULL);
17545  assert(aggrobj != NULL);
17546 
17547  while( probvar != NULL )
17548  {
17549  switch( SCIPvarGetStatus(probvar) )
17550  {
17552  case SCIP_VARSTATUS_LOOSE:
17553  case SCIP_VARSTATUS_COLUMN:
17554  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17555  return SCIP_OKAY;
17556 
17557  case SCIP_VARSTATUS_FIXED:
17558  assert(SCIPvarGetObj(probvar) == 0.0);
17559  (*aggrobj) = 0.0;
17560  return SCIP_OKAY;
17561 
17563  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17564  if ( probvar->data.multaggr.nvars == 1 )
17565  {
17566  assert( probvar->data.multaggr.vars != NULL );
17567  assert( probvar->data.multaggr.scalars != NULL );
17568  assert( probvar->data.multaggr.vars[0] != NULL );
17569  mult *= probvar->data.multaggr.scalars[0];
17570  probvar = probvar->data.multaggr.vars[0];
17571  break;
17572  }
17573  else
17574  {
17575  SCIP_Real tmpobj;
17576  int v;
17577 
17578  (*aggrobj) = 0.0;
17579 
17580  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17581  {
17582  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17583  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17584  }
17585  return SCIP_OKAY;
17586  }
17587 
17588  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17589  assert(probvar->data.aggregate.var != NULL);
17590  mult *= probvar->data.aggregate.scalar;
17591  probvar = probvar->data.aggregate.var;
17592  break;
17593 
17594  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17595  assert(probvar->negatedvar != NULL);
17596  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17597  assert(probvar->negatedvar->negatedvar == probvar);
17598  mult *= -1.0;
17599  probvar = probvar->negatedvar;
17600  break;
17601 
17602  default:
17603  SCIPABORT();
17604  return SCIP_INVALIDDATA; /*lint !e527*/
17605  }
17606  }
17607 
17608  return SCIP_INVALIDDATA;
17609 }
17610 
17611 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17613  SCIP_VAR* var /**< original problem variable */
17614  )
17615 {
17616  assert(var != NULL);
17617  assert(SCIPvarIsOriginal(var));
17618 
17620  return var->data.original.origdom.lb;
17621  else
17622  {
17623  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17624  assert(var->negatedvar != NULL);
17626 
17627  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17628  }
17629 }
17630 
17631 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17633  SCIP_VAR* var /**< original problem variable */
17634  )
17635 {
17636  assert(var != NULL);
17637  assert(SCIPvarIsOriginal(var));
17638 
17640  return var->data.original.origdom.ub;
17641  else
17642  {
17643  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17644  assert(var->negatedvar != NULL);
17646 
17647  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17648  }
17649 }
17650 
17651 /** gets the original hole list of an original variable */
17653  SCIP_VAR* var /**< problem variable */
17654  )
17655 {
17656  assert(var != NULL);
17657  assert(SCIPvarIsOriginal(var));
17658 
17660  return var->data.original.origdom.holelist;
17661 
17662  return NULL;
17663 }
17664 
17665 /** gets global lower bound of variable */
17667  SCIP_VAR* var /**< problem variable */
17668  )
17669 {
17670  assert(var != NULL);
17671 
17672  return var->glbdom.lb;
17673 }
17674 
17675 /** gets global upper bound of variable */
17677  SCIP_VAR* var /**< problem variable */
17678  )
17679 {
17680  assert(var != NULL);
17681 
17682  return var->glbdom.ub;
17683 }
17684 
17685 /** gets the global hole list of an active variable */
17687  SCIP_VAR* var /**< problem variable */
17688  )
17689 {
17690  assert(var != NULL);
17691 
17692  return var->glbdom.holelist;
17693 }
17694 
17695 /** gets best global bound of variable with respect to the objective function */
17697  SCIP_VAR* var /**< problem variable */
17698  )
17699 {
17700  assert(var != NULL);
17701 
17702  if( var->obj >= 0.0 )
17703  return var->glbdom.lb;
17704  else
17705  return var->glbdom.ub;
17706 }
17707 
17708 /** gets worst global bound of variable with respect to the objective function */
17710  SCIP_VAR* var /**< problem variable */
17711  )
17712 {
17713  assert(var != NULL);
17714 
17715  if( var->obj >= 0.0 )
17716  return var->glbdom.ub;
17717  else
17718  return var->glbdom.lb;
17719 }
17720 
17721 /** gets current lower bound of variable */
17723  SCIP_VAR* var /**< problem variable */
17724  )
17725 {
17726  assert(var != NULL);
17727 
17728  return var->locdom.lb;
17729 }
17730 
17731 /** gets current upper bound of variable */
17733  SCIP_VAR* var /**< problem variable */
17734  )
17735 {
17736  assert(var != NULL);
17737 
17738  return var->locdom.ub;
17739 }
17740 
17741 /** gets the current hole list of an active variable */
17743  SCIP_VAR* var /**< problem variable */
17744  )
17745 {
17746  assert(var != NULL);
17747 
17748  return var->locdom.holelist;
17749 }
17750 
17751 /** gets best local bound of variable with respect to the objective function */
17753  SCIP_VAR* var /**< problem variable */
17754  )
17755 {
17756  assert(var != NULL);
17757 
17758  if( var->obj >= 0.0 )
17759  return var->locdom.lb;
17760  else
17761  return var->locdom.ub;
17762 }
17763 
17764 /** gets worst local bound of variable with respect to the objective function */
17766  SCIP_VAR* var /**< problem variable */
17767  )
17768 {
17769  assert(var != NULL);
17770 
17771  if( var->obj >= 0.0 )
17772  return var->locdom.ub;
17773  else
17774  return var->locdom.lb;
17775 }
17776 
17777 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17779  SCIP_VAR* var /**< problem variable */
17780  )
17781 {
17782  assert(var != NULL);
17783 
17784  if( var->obj >= 0.0 )
17785  return SCIP_BOUNDTYPE_LOWER;
17786  else
17787  return SCIP_BOUNDTYPE_UPPER;
17788 }
17789 
17790 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17792  SCIP_VAR* var /**< problem variable */
17793  )
17794 {
17795  assert(var != NULL);
17796 
17797  if( var->obj >= 0.0 )
17798  return SCIP_BOUNDTYPE_UPPER;
17799  else
17800  return SCIP_BOUNDTYPE_LOWER;
17801 }
17802 
17803 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17805  SCIP_VAR* var /**< problem variable */
17806  )
17807 {
17808  assert(var != NULL);
17809 
17810  return var->lazylb;
17811 }
17812 
17813 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17815  SCIP_VAR* var /**< problem variable */
17816  )
17817 {
17818  assert(var != NULL);
17819 
17820  return var->lazyub;
17821 }
17822 
17823 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17824  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17825  */
17827  SCIP_VAR* var /**< problem variable */
17828  )
17829 {
17830  assert(var != NULL);
17831 
17832  return var->branchfactor;
17833 }
17834 
17835 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17836  * with lower priority
17837  */
17839  SCIP_VAR* var /**< problem variable */
17840  )
17841 {
17842  assert(var != NULL);
17843 
17844  return var->branchpriority;
17845 }
17846 
17847 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17849  SCIP_VAR* var /**< problem variable */
17850  )
17851 {
17852  assert(var != NULL);
17853 
17854  return (SCIP_BRANCHDIR)var->branchdirection;
17855 }
17856 
17857 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17858 int SCIPvarGetNVlbs(
17859  SCIP_VAR* var /**< problem variable */
17860  )
17861 {
17862  assert(var != NULL);
17863 
17864  return SCIPvboundsGetNVbds(var->vlbs);
17865 }
17866 
17867 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17868  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17869  */
17871  SCIP_VAR* var /**< problem variable */
17872  )
17873 {
17874  assert(var != NULL);
17875 
17876  return SCIPvboundsGetVars(var->vlbs);
17877 }
17878 
17879 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17881  SCIP_VAR* var /**< problem variable */
17882  )
17883 {
17884  assert(var != NULL);
17885 
17886  return SCIPvboundsGetCoefs(var->vlbs);
17887 }
17888 
17889 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17891  SCIP_VAR* var /**< problem variable */
17892  )
17893 {
17894  assert(var != NULL);
17895 
17896  return SCIPvboundsGetConstants(var->vlbs);
17897 }
17898 
17899 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17900 int SCIPvarGetNVubs(
17901  SCIP_VAR* var /**< problem variable */
17902  )
17903 {
17904  assert(var != NULL);
17905 
17906  return SCIPvboundsGetNVbds(var->vubs);
17907 }
17908 
17909 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17910  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17911  */
17913  SCIP_VAR* var /**< problem variable */
17914  )
17915 {
17916  assert(var != NULL);
17917 
17918  return SCIPvboundsGetVars(var->vubs);
17919 }
17920 
17921 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17923  SCIP_VAR* var /**< problem variable */
17924  )
17925 {
17926  assert(var != NULL);
17927 
17928  return SCIPvboundsGetCoefs(var->vubs);
17929 }
17930 
17931 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17933  SCIP_VAR* var /**< problem variable */
17934  )
17935 {
17936  assert(var != NULL);
17937 
17938  return SCIPvboundsGetConstants(var->vubs);
17939 }
17940 
17941 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17942  * there are no implications for nonbinary variable x
17943  */
17944 int SCIPvarGetNImpls(
17945  SCIP_VAR* var, /**< active problem variable */
17946  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17947  )
17948 {
17949  assert(var != NULL);
17950  assert(SCIPvarIsActive(var));
17951 
17952  return SCIPimplicsGetNImpls(var->implics, varfixing);
17953 }
17954 
17955 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17956  * problem variable x, there are no implications for nonbinary variable x;
17957  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17958  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17959  * (see SCIPvarGetIndex())
17960  */
17962  SCIP_VAR* var, /**< active problem variable */
17963  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17964  )
17965 {
17966  assert(var != NULL);
17967  assert(SCIPvarIsActive(var));
17968 
17969  return SCIPimplicsGetVars(var->implics, varfixing);
17970 }
17971 
17972 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17973  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17974  * there are no implications for nonbinary variable x
17975  */
17977  SCIP_VAR* var, /**< active problem variable */
17978  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17979  )
17980 {
17981  assert(var != NULL);
17982  assert(SCIPvarIsActive(var));
17983 
17984  return SCIPimplicsGetTypes(var->implics, varfixing);
17985 }
17986 
17987 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17988  * variable x, there are no implications for nonbinary variable x
17989  */
17991  SCIP_VAR* var, /**< active problem variable */
17992  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17993  )
17994 {
17995  assert(var != NULL);
17996  assert(SCIPvarIsActive(var));
17997 
17998  return SCIPimplicsGetBounds(var->implics, varfixing);
17999 }
18000 
18001 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
18002  * there are no implications for nonbinary variable x.
18003  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
18004  * its id is negative, otherwise it is nonnegative.
18005  */
18006 int* SCIPvarGetImplIds(
18007  SCIP_VAR* var, /**< active problem variable */
18008  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
18009  )
18010 {
18011  assert(var != NULL);
18012  assert(SCIPvarIsActive(var));
18013 
18014  return SCIPimplicsGetIds(var->implics, varfixing);
18015 }
18016 
18017 /** gets number of cliques, the active variable is contained in */
18018 int SCIPvarGetNCliques(
18019  SCIP_VAR* var, /**< active problem variable */
18020  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18021  )
18022 {
18023  assert(var != NULL);
18024 
18025  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
18026 }
18027 
18028 /** gets array of cliques, the active variable is contained in */
18030  SCIP_VAR* var, /**< active problem variable */
18031  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
18032  )
18033 {
18034  assert(var != NULL);
18035 
18036  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
18037 }
18038 
18039 /** gets primal LP solution value of variable */
18041  SCIP_VAR* var /**< problem variable */
18042  )
18043 {
18044  assert(var != NULL);
18045 
18047  return SCIPcolGetPrimsol(var->data.col);
18048  else
18049  return SCIPvarGetLPSol_rec(var);
18050 }
18051 
18052 /** gets primal NLP solution value of variable */
18054  SCIP_VAR* var /**< problem variable */
18055  )
18056 {
18057  assert(var != NULL);
18058 
18060  return var->nlpsol;
18061  else
18062  return SCIPvarGetNLPSol_rec(var);
18063 }
18064 
18065 /** return lower bound change info at requested position */
18067  SCIP_VAR* var, /**< problem variable */
18068  int pos /**< requested position */
18069  )
18070 {
18071  assert(pos >= 0);
18072  assert(pos < var->nlbchginfos);
18073 
18074  return &var->lbchginfos[pos];
18075 }
18076 
18077 /** gets the number of lower bound change info array */
18079  SCIP_VAR* var /**< problem variable */
18080  )
18081 {
18082  return var->nlbchginfos;
18083 }
18084 
18085 /** return upper bound change info at requested position */
18087  SCIP_VAR* var, /**< problem variable */
18088  int pos /**< requested position */
18089  )
18090 {
18091  assert(pos >= 0);
18092  assert(pos < var->nubchginfos);
18093 
18094  return &var->ubchginfos[pos];
18095 }
18096 
18097 /** gets the number upper bound change info array */
18099  SCIP_VAR* var /**< problem variable */
18100  )
18101 {
18102  assert(var != NULL);
18103 
18104  return var->nubchginfos;
18105 }
18106 
18107 /** returns the value based history for the variable */
18109  SCIP_VAR* var /**< problem variable */
18110  )
18111 {
18112  assert(var != NULL);
18113 
18114  return var->valuehistory;
18115 }
18116 
18117 /** gets pseudo solution value of variable */
18119  SCIP_VAR* var /**< problem variable */
18120  )
18121 {
18122  assert(var != NULL);
18123 
18125  return SCIPvarGetBestBoundLocal(var);
18126  else
18127  return SCIPvarGetPseudoSol_rec(var);
18128 }
18129 
18130 /** returns the variable's VSIDS score */
18132  SCIP_VAR* var, /**< problem variable */
18133  SCIP_STAT* stat, /**< problem statistics */
18134  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
18135  )
18136 {
18137  assert(var != NULL);
18138 
18140  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
18141  else
18142  return SCIPvarGetVSIDS_rec(var, stat, dir);
18143 }
18144 
18145 /** includes event handler with given data in variable's event filter */
18147  SCIP_VAR* var, /**< problem variable */
18148  BMS_BLKMEM* blkmem, /**< block memory */
18149  SCIP_SET* set, /**< global SCIP settings */
18150  SCIP_EVENTTYPE eventtype, /**< event type to catch */
18151  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18152  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18153  int* filterpos /**< pointer to store position of event filter entry, or NULL */
18154  )
18155 {
18156  assert(var != NULL);
18157  assert(set != NULL);
18158  assert(var->scip == set->scip);
18159  assert(var->eventfilter != NULL);
18160  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
18161  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
18162  assert(SCIPvarIsTransformed(var));
18163 
18164  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
18165  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
18166 
18167  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18168 
18169  return SCIP_OKAY;
18170 }
18171 
18172 /** deletes event handler with given data from variable's event filter */
18174  SCIP_VAR* var, /**< problem variable */
18175  BMS_BLKMEM* blkmem, /**< block memory */
18176  SCIP_SET* set, /**< global SCIP settings */
18177  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
18178  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
18179  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
18180  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
18181  )
18182 {
18183  assert(var != NULL);
18184  assert(set != NULL);
18185  assert(var->scip == set->scip);
18186  assert(var->eventfilter != NULL);
18187  assert(SCIPvarIsTransformed(var));
18188 
18189  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
18190  (void*)eventdata);
18191 
18192  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
18193 
18194  return SCIP_OKAY;
18195 }
18196 
18197 /** returns the position of the bound change index */
18198 int SCIPbdchgidxGetPos(
18199  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
18200  )
18201 {
18202  assert(bdchgidx != NULL);
18203 
18204  return bdchgidx->pos;
18205 }
18206 
18207 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
18209  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
18210  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
18211  )
18212 {
18213  assert(bdchgidx1 != NULL);
18214  assert(bdchgidx1->depth >= -2);
18215  assert(bdchgidx1->pos >= 0);
18216  assert(bdchgidx2 != NULL);
18217  assert(bdchgidx2->depth >= -2);
18218  assert(bdchgidx2->pos >= 0);
18219 
18220  return (bdchgidx1->depth < bdchgidx2->depth)
18221  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18222 }
18223 
18224 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
18225  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
18226  * last bound change was applied to the current node
18227  */
18229  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
18230  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
18231  )
18232 {
18233  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
18234  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
18235  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
18236  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
18237 
18238  if( bdchgidx1 == NULL )
18239  return FALSE;
18240  else if( bdchgidx2 == NULL )
18241  return TRUE;
18242  else
18243  return (bdchgidx1->depth < bdchgidx2->depth)
18244  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
18245 }
18246 
18247 /** returns old bound that was overwritten for given bound change information */
18249  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18250  )
18251 {
18252  assert(bdchginfo != NULL);
18253 
18254  return bdchginfo->oldbound;
18255 }
18256 
18257 /** returns new bound installed for given bound change information */
18259  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18260  )
18261 {
18262  assert(bdchginfo != NULL);
18263 
18264  return bdchginfo->newbound;
18265 }
18266 
18267 /** returns variable that belongs to the given bound change information */
18269  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18270  )
18271 {
18272  assert(bdchginfo != NULL);
18273 
18274  return bdchginfo->var;
18275 }
18276 
18277 /** returns whether the bound change information belongs to a branching decision or a deduction */
18279  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18280  )
18281 {
18282  assert(bdchginfo != NULL);
18283 
18284  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
18285 }
18286 
18287 /** returns whether the bound change information belongs to a lower or upper bound change */
18289  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18290  )
18291 {
18292  assert(bdchginfo != NULL);
18293 
18294  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
18295 }
18296 
18297 /** returns depth level of given bound change information */
18299  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18300  )
18301 {
18302  assert(bdchginfo != NULL);
18303 
18304  return bdchginfo->bdchgidx.depth;
18305 }
18306 
18307 /** returns bound change position in its depth level of given bound change information */
18309  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18310  )
18311 {
18312  assert(bdchginfo != NULL);
18313 
18314  return bdchginfo->bdchgidx.pos;
18315 }
18316 
18317 /** returns bound change index of given bound change information */
18319  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18320  )
18321 {
18322  assert(bdchginfo != NULL);
18323 
18324  return &bdchginfo->bdchgidx;
18325 }
18326 
18327 /** returns inference variable of given bound change information */
18329  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18330  )
18331 {
18332  assert(bdchginfo != NULL);
18335 
18336  return bdchginfo->inferencedata.var;
18337 }
18338 
18339 /** returns inference constraint of given bound change information */
18341  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18342  )
18343 {
18344  assert(bdchginfo != NULL);
18346  assert(bdchginfo->inferencedata.reason.cons != NULL);
18347 
18348  return bdchginfo->inferencedata.reason.cons;
18349 }
18350 
18351 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
18353  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18354  )
18355 {
18356  assert(bdchginfo != NULL);
18358 
18359  return bdchginfo->inferencedata.reason.prop;
18360 }
18361 
18362 /** returns inference user information of given bound change information */
18364  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18365  )
18366 {
18367  assert(bdchginfo != NULL);
18370 
18371  return bdchginfo->inferencedata.info;
18372 }
18373 
18374 /** returns inference bound of inference variable of given bound change information */
18376  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18377  )
18378 {
18379  assert(bdchginfo != NULL);
18382 
18383  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
18384 }
18385 
18386 /** returns the relaxed bound change type */
18388  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
18389  )
18390 {
18391  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18392 }
18393 
18394 
18395 /** returns whether the bound change information belongs to a redundant bound change */
18397  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18398  )
18399 {
18400  assert(bdchginfo != NULL);
18401  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18402 
18403  return bdchginfo->redundant;
18404 }
18405 
18406 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18408  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18409  )
18410 {
18411  assert(bdchginfo != NULL);
18412 
18415  && bdchginfo->inferencedata.reason.prop != NULL);
18416 }
18417 
18418 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18419  * has a tighter new bound as the second bound change
18420  */
18422  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18423  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18424  )
18425 {
18426  assert(bdchginfo1 != NULL);
18427  assert(bdchginfo2 != NULL);
18428  assert(bdchginfo1->var == bdchginfo2->var);
18429  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18430 
18431  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18432  ? bdchginfo1->newbound > bdchginfo2->newbound
18433  : bdchginfo1->newbound < bdchginfo2->newbound);
18434 }
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:11762
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:96
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18388
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17753
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:3096
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15169
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5987
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:17159
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:13889
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:9191
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:15296
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:17172
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6045
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6495
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:17743
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:14816
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:9073
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13583
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:10274
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:17027
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13049
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:479
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13773
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:17684
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17413
int nubchginfos
Definition: struct_var.h:260
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:16077
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:231
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5894
unsigned int inferboundtype
Definition: struct_var.h:93
unsigned int relaxationonly
Definition: struct_var.h:276
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17392
char * name
Definition: struct_var.h:226
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:16568
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:204
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6174
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:17370
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:6644
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6385
#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:6994
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:87
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5729
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:14383
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:18054
methods for implications, variable bounds, and cliques
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:17082
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:14549
#define SCIP_MAXSTRLEN
Definition: def.h:279
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:18109
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15464
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:6376
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17827
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17815
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:6110
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:268
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:13183
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18397
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:16131
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:7278
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:18041
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:205
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8375
SCIP_HISTORY * historycrun
Definition: struct_var.h:242
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:175
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:18087
SCIP_EXPORT SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7438
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:9022
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:17250
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:6435
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:113
SCIP_Longint closestvblpcount
Definition: struct_var.h:244
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8683
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:6571
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3269
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5852
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:240
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:5952
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14902
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12703
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:18119
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:18147
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:17197
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:17962
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:5872
#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:10735
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:17674
datastructures for managing events
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6528
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:17515
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16914
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:16964
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:69
int nlocksup[NLOCKTYPES]
Definition: struct_var.h:255
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17687
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:12240
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6099
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:17182
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14788
#define TRUE
Definition: def.h:72
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5853
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15125
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:15597
#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:258
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16588
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:12632
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:10721
#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:8058
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5887
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5580
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:66
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:17058
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:8032
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:7137
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:17340
public methods for problem variables
static GRAPHNODE ** active
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12840
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:15832
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:17261
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17991
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:11044
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11705
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:11777
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:16817
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:17136
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:18199
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11770
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3426
int index
Definition: struct_var.h:245
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:6121
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:5987
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:13483
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16643
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:14144
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1692
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6326
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:267
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11590
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:200
SCIP_EXPORT SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7718
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:207
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:6185
int conflictlbcount
Definition: struct_var.h:261
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13762
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:5864
internal methods for LP management
Definition: heur_padm.c:125
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16827
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17871
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12912
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:256
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:17459
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:12773
int nrootboundchgs
Definition: struct_stat.h:210
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:17070
#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:6081
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:7355
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:170
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:13119
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15693
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:18329
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1415
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:17218
SCIP_Real conflictrelaxedub
Definition: struct_var.h:213
unsigned int inferboundtype
Definition: struct_var.h:116
SCIP_Bool SCIPvarIsRelaxationOnly(SCIP_VAR *var)
Definition: var.c:17304
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:7779
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18279
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3363
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6027
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12657
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:11270
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:13236
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:17104
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16954
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:16972
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:250
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:212
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11460
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14242
SCIP_AGGREGATE aggregate
Definition: struct_var.h:222
SCIP_Real lazylb
Definition: struct_var.h:214
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:13026
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:453
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:17017
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:7393
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:17330
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:7301
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:7613
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:17208
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18422
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:13232
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18007
#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:12049
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:10705
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:234
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:16585
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:14692
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:17483
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15987
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17805
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17945
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:6074
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16934
int lbchginfossize
Definition: struct_var.h:257
unsigned int varstatus
Definition: struct_var.h:271
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17792
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17839
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18299
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:206
SCIP_VARDATA * vardata
Definition: struct_var.h:231
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6263
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17537
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:189
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:14291
SCIP_Real primsolavg
Definition: struct_var.h:209
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:17923
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:269
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:6820
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:6563
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:265
#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:13964
SCIP_NEGATE negate
Definition: struct_var.h:224
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16308
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:7446
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13629
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:169
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:17093
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3277
#define REALABS(x)
Definition: def.h:187
int nparentvars
Definition: struct_var.h:252
SCIP_Real unchangedobj
Definition: struct_var.h:201
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11675
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16231
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:9810
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15033
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:14511
#define SCIP_CALL(x)
Definition: def.h:370
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17901
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16860
SCIP_VBOUNDS * vubs
Definition: struct_var.h:235
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6473
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:186
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:15212
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16837
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2354
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15744
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14338
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:9529
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5680
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3285
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18353
Definition: grphload.c:88
int closestvubidx
Definition: struct_var.h:264
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14426
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:6009
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11404
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:7906
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:261
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17424
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15080
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16175
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:17504
SCIP_EXPORT void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
unsigned int branchdirection
Definition: struct_var.h:273
int ubchginfossize
Definition: struct_var.h:259
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1579
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6429
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10940
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:262
#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:16591
int nlocksdown[NLOCKTYPES]
Definition: struct_var.h:254
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6360
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3347
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:17381
#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:6039
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:11334
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:5160
#define SCIP_UNKNOWN
Definition: def.h:184
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6132
public data structures and miscellaneous methods
unsigned int vartype
Definition: struct_var.h:270
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10920
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:17493
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:15380
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:6495
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:8802
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:17471
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2774
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18408
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18209
#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:11989
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16984
unsigned int deletable
Definition: struct_var.h:267
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15789
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:5905
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:17120
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6195
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17677
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:13038
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:17779
SCIP_Bool divingobjchg
Definition: struct_lp.h:371
SCIP_MULTAGGR multaggr
Definition: struct_var.h:223
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:8148
#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:9295
unsigned int deleted
Definition: struct_var.h:268
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:17766
#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:11756
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18364
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:17146
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:15552
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17525
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3363
public methods for LP management
unsigned int removable
Definition: struct_var.h:266
#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:17047
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:8441
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:15509
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11167
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16628
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:18229
int closestvlbidx
Definition: struct_var.h:263
#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:18289
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18376
int nuses
Definition: struct_var.h:253
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15889
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:10953
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11206
#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:246
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8554
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:17238
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17613
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:13690
datastructures for problem statistics
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:18030
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:6407
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:6149
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:14952
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:9321
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17723
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:17004
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:278
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:238
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12960
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2253
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18309
int conflictubcount
Definition: struct_var.h:262
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:217
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:9602
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:6717
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:243
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c: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:17710
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:14036
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:17733
methods for sorting joint arrays of various types
SCIP_VAR ** parentvars
Definition: struct_var.h:232
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:6552
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:7327
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18269
#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:6183
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18341
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:5326
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8448
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:2078
SCIP_Real lazyub
Definition: struct_var.h:215
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:15944
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17667
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:16979
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:12333
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17881
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17435
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:14626
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17891
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:18067
SCIP_VAR * a
Definition: circlepacking.c:57
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10604
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:9093
SCIP_Real * scalars
Definition: struct_var.h:185
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:18099
SCIP_IMPLICS * implics
Definition: struct_var.h:236
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6063
datastructures for problem variables
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17274
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:9040
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:8077
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:9222
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:16427
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6506
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:251
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:237
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:12545
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:18132
#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:16287
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:17319
SCIP_Real branchfactor
Definition: struct_var.h:202
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17977
unsigned int donotmultaggr
Definition: struct_var.h:269
#define SCIP_Longint
Definition: def.h:148
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6706
SCIP_Real nlpsol
Definition: struct_var.h:208
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:11249
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:16030
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:6451
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:8931
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8309
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:16895
SCIP_DOM glbdom
Definition: struct_var.h:216
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5874
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:649
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16924
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2924
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:17360
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:6533
SCIP_Bool collectvarhistory
Definition: struct_stat.h:268
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:12081
SCIP_VAR * negatedvar
Definition: struct_var.h:233
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:17284
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:8502
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:16161
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6343
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6603
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:443
unsigned int delglobalstructs
Definition: struct_var.h:275
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6728
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:17037
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:18174
SCIP_Real rootsol
Definition: struct_var.h:203
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:13614
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17402
SCIP_HISTORY * history
Definition: struct_var.h:241
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17633
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15642
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:18019
union SCIP_BoundChg::@13 data
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12418
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:67
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16944
#define SCIP_CALL_ABORT(x)
Definition: def.h:349
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17653
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:17228
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3320
SCIP_ORIGINAL original
Definition: struct_var.h:220
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:9274
#define SCIP_ALLOC(x)
Definition: def.h:381
#define SCIPABORT()
Definition: def.h:342
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13549
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:17849
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8243
unsigned int applied
Definition: struct_var.h:94
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16994
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17933
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:11129
datastructures for global SCIP settings
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17913
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11969
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16548
#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:5941
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13829
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18249
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16716
SCIP_COL * col
Definition: struct_var.h:221
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5764
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:17447
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18319
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18259
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:11523
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:17697
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6517
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17859
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14457
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:17350
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:239
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14761
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:11713
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:18079
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:11189