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-2017 Konrad-Zuse-Zentrum */
7 /* fuer Informationstechnik Berlin */
8 /* */
9 /* SCIP is distributed under the terms of the ZIB Academic License. */
10 /* */
11 /* You should have received a copy of the ZIB Academic License */
12 /* along with SCIP; see the file COPYING. If not email to scip@zib.de. */
13 /* */
14 /* * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * * */
15 
16 /**@file var.c
17  * @brief methods for problem variables
18  * @author Tobias Achterberg
19  * @author Timo Berthold
20  * @author Gerald Gamrath
21  * @author Stefan Heinz
22  * @author Marc Pfetsch
23  * @author Michael Winkler
24  * @author Kati Wolter
25  * @author Stefan Vigerske
26  *
27  * @todo Possibly implement the access of bounds of multi-aggregated variables by accessing the
28  * corresponding linear constraint if it exists. This seems to require some work, since the linear
29  * constraint has to be stored. Moreover, it has even to be created in case the original constraint
30  * was deleted after multi-aggregation, but the bounds of the multi-aggregated variable should be
31  * changed. This has to be done with care in order to not loose the performance gains of
32  * multi-aggregation.
33  */
34 
35 /*---+----1----+----2----+----3----+----4----+----5----+----6----+----7----+----8----+----9----+----0----+----1----+----2*/
36 
37 #include <stdlib.h>
38 #include <assert.h>
39 #include <string.h>
40 
41 #include "scip/def.h"
42 #include "scip/prop.h"
43 #include "scip/relax.h"
44 #include "scip/var.h"
45 #include "scip/cons.h"
46 #include "scip/event.h"
47 #include "scip/history.h"
48 #include "scip/implics.h"
49 #include "scip/lp.h"
50 #include "scip/primal.h"
51 #include "scip/prob.h"
52 #include "scip/set.h"
53 #include "scip/sol.h"
54 #include "scip/stat.h"
55 #include "scip/tree.h"
56 #include "scip/reopt.h"
57 
58 #include "scip/debug.h"
59 
60 #include "scip/pub_message.h"
61 #include "scip/pub_history.h"
62 
63 #define MAXIMPLSCLOSURE 100 /**< maximal number of descendants of implied variable for building closure
64  * in implication graph */
65 #define MAXABSVBCOEF 1e+5 /**< maximal absolute coefficient in variable bounds added due to implications */
66 
67 /*
68  * hole, holelist, and domain methods
69  */
70 
71 /** creates a new holelist element */
72 static
74  SCIP_HOLELIST** holelist, /**< pointer to holelist to create */
75  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
76  SCIP_SET* set, /**< global SCIP settings */
77  SCIP_Real left, /**< left bound of open interval in new hole */
78  SCIP_Real right /**< right bound of open interval in new hole */
79  )
80 {
81  assert(holelist != NULL);
82  assert(blkmem != NULL);
83  assert(SCIPsetIsLT(set, left, right));
84 
85  SCIPsetDebugMsg(set, "create hole list element (%.15g,%.15g) in blkmem %p\n", left, right, (void*)blkmem);
86 
87  SCIP_ALLOC( BMSallocBlockMemory(blkmem, holelist) );
88  (*holelist)->hole.left = left;
89  (*holelist)->hole.right = right;
90  (*holelist)->next = NULL;
91 
92  return SCIP_OKAY;
93 }
94 
95 /** frees all elements in the holelist */
96 static
97 void holelistFree(
98  SCIP_HOLELIST** holelist, /**< pointer to holelist to free */
99  BMS_BLKMEM* blkmem /**< block memory for target holelist */
100  )
101 {
102  assert(holelist != NULL);
103  assert(blkmem != NULL);
104 
105  while( *holelist != NULL )
106  {
107  SCIP_HOLELIST* next;
108 
109  SCIPdebugMessage("free hole list element (%.15g,%.15g) in blkmem %p\n",
110  (*holelist)->hole.left, (*holelist)->hole.right, (void*)blkmem);
111 
112  next = (*holelist)->next;
113  BMSfreeBlockMemory(blkmem, holelist);
114  assert(*holelist == NULL);
115 
116  *holelist = next;
117  }
118  assert(*holelist == NULL);
119 }
120 
121 /** duplicates a list of holes */
122 static
124  SCIP_HOLELIST** target, /**< pointer to target holelist */
125  BMS_BLKMEM* blkmem, /**< block memory for target holelist */
126  SCIP_SET* set, /**< global SCIP settings */
127  SCIP_HOLELIST* source /**< holelist to duplicate */
128  )
129 {
130  assert(target != NULL);
131 
132  while( source != NULL )
133  {
134  assert(source->next == NULL || SCIPsetIsGE(set, source->next->hole.left, source->hole.right));
135  SCIP_CALL( holelistCreate(target, blkmem, set, source->hole.left, source->hole.right) );
136  source = source->next;
137  target = &(*target)->next;
138  }
139 
140  return SCIP_OKAY;
141 }
142 
143 /** adds a hole to the domain */
144 static
146  SCIP_DOM* dom, /**< domain to add hole to */
147  BMS_BLKMEM* blkmem, /**< block memory */
148  SCIP_SET* set, /**< global SCIP settings */
149  SCIP_Real left, /**< left bound of open interval in new hole */
150  SCIP_Real right, /**< right bound of open interval in new hole */
151  SCIP_Bool* added /**< pointer to store whether the hole was added (variable didn't had that hole before), or NULL */
152  )
153 {
154  SCIP_HOLELIST** insertpos;
155  SCIP_HOLELIST* next;
156 
157  assert(dom != NULL);
158  assert(added != NULL);
159 
160  /* search for the position of the new hole */
161  insertpos = &dom->holelist;
162  while( *insertpos != NULL && (*insertpos)->hole.left < left )
163  insertpos = &(*insertpos)->next;
164 
165  /* check if new hole already exists in the hole list or is a sub hole of an existing one */
166  if( *insertpos != NULL && (*insertpos)->hole.left == left && (*insertpos)->hole.right >= right ) /*lint !e777 */
167  {
168  SCIPsetDebugMsg(set, "new hole (%.15g,%.15g) is redundant through known hole (%.15g,%.15g)\n",
169  left, right, (*insertpos)->hole.left, (*insertpos)->hole.right);
170  *added = FALSE;
171  return SCIP_OKAY;
172  }
173 
174  /* add hole */
175  *added = TRUE;
176 
177  next = *insertpos;
178  SCIP_CALL( holelistCreate(insertpos, blkmem, set, left, right) );
179  (*insertpos)->next = next;
180 
181  return SCIP_OKAY;
182 }
183 
184 /** merges overlapping holes into single holes, computes and moves lower and upper bound, respectively */
185 /**@todo the domMerge() method is currently called if a lower or an upper bound locally or globally changed; this could
186  * be more efficient if performed with the knowledge if it was a lower or an upper bound which triggered this
187  * merge */
188 static
189 void domMerge(
190  SCIP_DOM* dom, /**< domain to merge */
191  BMS_BLKMEM* blkmem, /**< block memory */
192  SCIP_SET* set, /**< global SCIP settings */
193  SCIP_Real* newlb, /**< pointer to store new lower bound */
194  SCIP_Real* newub /**< pointer to store new upper bound */
195  )
196 {
197  SCIP_HOLELIST** holelistptr;
198  SCIP_HOLELIST** lastnextptr;
199  SCIP_Real* lastrightptr;
200 
201  assert(dom != NULL);
202  assert(SCIPsetIsLE(set, dom->lb, dom->ub));
203 
204 #ifndef NDEBUG
205  {
206  /* check if the holelist is sorted w.r.t. to the left interval bounds */
207  SCIP_Real lastleft;
208 
209  holelistptr = &dom->holelist;
210 
211  lastleft = -SCIPsetInfinity(set);
212 
213  while( *holelistptr != NULL )
214  {
215  if( (*holelistptr)->next != NULL )
216  {
217  assert( SCIPsetIsLE(set, lastleft, (*holelistptr)->hole.left) );
218  lastleft = (*holelistptr)->hole.left;
219  }
220 
221  holelistptr = &(*holelistptr)->next;
222  }
223  }
224 #endif
225 
226  SCIPsetDebugMsg(set, "merge hole list\n");
227 
228  holelistptr = &dom->holelist;
229  lastrightptr = &dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
230  lastnextptr = holelistptr;
231 
232  while( *holelistptr != NULL )
233  {
234  SCIPsetDebugMsg(set, "check hole (%.15g,%.15g) last right interval was <%.15g>\n", (*holelistptr)->hole.left, (*holelistptr)->hole.right, *lastrightptr);
235 
236  /* check that the hole is not empty */
237  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right));
238 
239  if( SCIPsetIsGE(set, (*holelistptr)->hole.left, dom->ub) )
240  {
241  /* the remaining holes start behind the upper bound: remove them */
242  SCIPsetDebugMsg(set, "remove remaining hole since upper bound <%.15g> is less then the left hand side of the current hole\n", dom->ub);
243  holelistFree(holelistptr, blkmem);
244  assert(*holelistptr == NULL);
245 
246  /* unlink this hole from the previous hole */
247  *lastnextptr = NULL;
248  }
249  else if( SCIPsetIsGT(set, (*holelistptr)->hole.right, dom->ub) )
250  {
251  /* the hole overlaps the upper bound: decrease upper bound, remove this hole and all remaining holes */
252  SCIPsetDebugMsg(set, "upper bound <%.15g> lays in current hole; store new upper bound and remove this and all remaining holes\n", dom->ub);
253 
254  assert(SCIPsetIsLT(set, (*holelistptr)->hole.left, dom->ub));
255 
256  /* adjust upper bound */
257  dom->ub = (*holelistptr)->hole.left;
258 
259  if(newub != NULL )
260  *newub = (*holelistptr)->hole.left;
261 
262  /* remove remaining hole list */
263  holelistFree(holelistptr, blkmem);
264  assert(*holelistptr == NULL);
265 
266  /* unlink this hole from the previous hole */
267  *lastnextptr = NULL;
268  }
269  else if( SCIPsetIsGT(set, *lastrightptr, (*holelistptr)->hole.left) )
270  {
271  /* the right bound of the last hole is greater than the left bound of this hole: increase the right bound of
272  * the last hole, delete this hole */
273  SCIP_HOLELIST* nextholelist;
274 
275  if( SCIPsetIsEQ(set, *lastrightptr, dom->lb ) )
276  {
277  /* the reason for the overlap results from the lower bound hole (-infinity,lb); therefore, we can increase
278  * the lower bound */
279  SCIPsetDebugMsg(set, "lower bound <%.15g> lays in current hole; store new lower bound and remove hole\n", dom->lb);
280  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
281 
282  /* adjust lower bound */
283  dom->lb = *lastrightptr;
284 
285  if(newlb != NULL )
286  *newlb = *lastrightptr;
287  }
288  else
289  {
290  SCIPsetDebugMsg(set, "current hole overlaps with the previous one (...,%.15g); merge to (...,%.15g)\n",
291  *lastrightptr, MAX(*lastrightptr, (*holelistptr)->hole.right) );
292  *lastrightptr = MAX(*lastrightptr, (*holelistptr)->hole.right);
293  }
294  nextholelist = (*holelistptr)->next;
295  (*holelistptr)->next = NULL;
296  holelistFree(holelistptr, blkmem);
297 
298  /* connect the linked list after removing the hole */
299  *lastnextptr = nextholelist;
300 
301  /* get next hole */
302  *holelistptr = nextholelist;
303  }
304  else
305  {
306  /* the holes do not overlap: update lastholelist and lastrightptr */
307  lastrightptr = &(*holelistptr)->hole.right;
308  lastnextptr = &(*holelistptr)->next;
309 
310  /* get next hole */
311  holelistptr = &(*holelistptr)->next;
312  }
313  }
314 
315 #ifndef NDEBUG
316  {
317  /* check that holes are merged */
318  SCIP_Real lastright;
319 
320  lastright = dom->lb; /* lower bound is the right bound of the hole (-infinity,lb) */
321  holelistptr = &dom->holelist;
322 
323  while( *holelistptr != NULL )
324  {
325  /* check the the last right interval is smaller or equal to the current left interval (none overlapping) */
326  assert( SCIPsetIsLE(set, lastright, (*holelistptr)->hole.left) );
327 
328  /* check the hole property (check that the hole is not empty) */
329  assert( SCIPsetIsLT(set, (*holelistptr)->hole.left, (*holelistptr)->hole.right) );
330  lastright = (*holelistptr)->hole.right;
331 
332  /* get next hole */
333  holelistptr = &(*holelistptr)->next;
334  }
335 
336  /* check the the last right interval is smaller or equal to the upper bound (none overlapping) */
337  assert( SCIPsetIsLE(set, lastright, dom->ub) );
338  }
339 #endif
340 }
341 
342 /*
343  * domain change methods
344  */
345 
346 /** ensures, that bound change info array for lower bound changes can store at least num entries */
347 static
349  SCIP_VAR* var, /**< problem variable */
350  BMS_BLKMEM* blkmem, /**< block memory */
351  SCIP_SET* set, /**< global SCIP settings */
352  int num /**< minimum number of entries to store */
353  )
354 {
355  assert(var != NULL);
356  assert(var->nlbchginfos <= var->lbchginfossize);
357  assert(SCIPvarIsTransformed(var));
358 
359  if( num > var->lbchginfossize )
360  {
361  int newsize;
362 
363  newsize = SCIPsetCalcMemGrowSize(set, num);
364  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->lbchginfos, var->lbchginfossize, newsize) );
365  var->lbchginfossize = newsize;
366  }
367  assert(num <= var->lbchginfossize);
368 
369  return SCIP_OKAY;
370 }
371 
372 /** ensures, that bound change info array for upper bound changes can store at least num entries */
373 static
375  SCIP_VAR* var, /**< problem variable */
376  BMS_BLKMEM* blkmem, /**< block memory */
377  SCIP_SET* set, /**< global SCIP settings */
378  int num /**< minimum number of entries to store */
379  )
380 {
381  assert(var != NULL);
382  assert(var->nubchginfos <= var->ubchginfossize);
383  assert(SCIPvarIsTransformed(var));
384 
385  if( num > var->ubchginfossize )
386  {
387  int newsize;
388 
389  newsize = SCIPsetCalcMemGrowSize(set, num);
390  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->ubchginfos, var->ubchginfossize, newsize) );
391  var->ubchginfossize = newsize;
392  }
393  assert(num <= var->ubchginfossize);
394 
395  return SCIP_OKAY;
396 }
397 
398 /** adds domain change info to the variable's lower bound change info array */
399 static
401  SCIP_VAR* var, /**< problem variable */
402  BMS_BLKMEM* blkmem, /**< block memory */
403  SCIP_SET* set, /**< global SCIP settings */
404  SCIP_Real oldbound, /**< old value for bound */
405  SCIP_Real newbound, /**< new value for bound */
406  int depth, /**< depth in the tree, where the bound change takes place */
407  int pos, /**< position of the bound change in its bound change array */
408  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
409  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
410  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
411  int inferinfo, /**< user information for inference to help resolving the conflict */
412  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
413  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
414  )
415 {
416  assert(var != NULL);
417  assert(SCIPsetIsLT(set, oldbound, newbound));
418  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
419  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
420  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 0.0));
421  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 1.0));
422  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
423  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
424  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
425 
426  SCIPsetDebugMsg(set, "adding lower bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
427  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
428  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
429  oldbound, newbound);
430 
431  SCIP_CALL( varEnsureLbchginfosSize(var, blkmem, set, var->nlbchginfos+1) );
432  var->lbchginfos[var->nlbchginfos].oldbound = oldbound;
433  var->lbchginfos[var->nlbchginfos].newbound = newbound;
434  var->lbchginfos[var->nlbchginfos].var = var;
435  var->lbchginfos[var->nlbchginfos].bdchgidx.depth = depth;
436  var->lbchginfos[var->nlbchginfos].bdchgidx.pos = pos;
437  var->lbchginfos[var->nlbchginfos].pos = var->nlbchginfos; /*lint !e732*/
438  var->lbchginfos[var->nlbchginfos].boundchgtype = boundchgtype; /*lint !e641*/
439  var->lbchginfos[var->nlbchginfos].boundtype = SCIP_BOUNDTYPE_LOWER; /*lint !e641*/
440  var->lbchginfos[var->nlbchginfos].redundant = FALSE;
441  var->lbchginfos[var->nlbchginfos].inferboundtype = inferboundtype; /*lint !e641*/
442  var->lbchginfos[var->nlbchginfos].inferencedata.var = infervar;
443  var->lbchginfos[var->nlbchginfos].inferencedata.info = inferinfo;
444 
445  /**@note The "pos" data member of the bound change info has a size of 27 bits */
446  assert(var->nlbchginfos < 1 << 27);
447 
448  switch( boundchgtype )
449  {
451  break;
453  assert(infercons != NULL);
454  var->lbchginfos[var->nlbchginfos].inferencedata.reason.cons = infercons;
455  break;
457  var->lbchginfos[var->nlbchginfos].inferencedata.reason.prop = inferprop;
458  break;
459  default:
460  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
461  return SCIP_INVALIDDATA;
462  }
463 
464  var->nlbchginfos++;
465 
466  assert(var->nlbchginfos < 2
468  &var->lbchginfos[var->nlbchginfos-1].bdchgidx));
469 
470  return SCIP_OKAY;
471 }
472 
473 /** adds domain change info to the variable's upper bound change info array */
474 static
476  SCIP_VAR* var, /**< problem variable */
477  BMS_BLKMEM* blkmem, /**< block memory */
478  SCIP_SET* set, /**< global SCIP settings */
479  SCIP_Real oldbound, /**< old value for bound */
480  SCIP_Real newbound, /**< new value for bound */
481  int depth, /**< depth in the tree, where the bound change takes place */
482  int pos, /**< position of the bound change in its bound change array */
483  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself) */
484  SCIP_CONS* infercons, /**< constraint that infered this bound change, or NULL */
485  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
486  int inferinfo, /**< user information for inference to help resolving the conflict */
487  SCIP_BOUNDTYPE inferboundtype, /**< type of bound for inference var: lower or upper bound */
488  SCIP_BOUNDCHGTYPE boundchgtype /**< bound change type: branching decision or infered bound change */
489  )
490 {
491  assert(var != NULL);
492  assert(SCIPsetIsGT(set, oldbound, newbound));
493  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, oldbound));
494  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
495  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, oldbound, 1.0));
496  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, 0.0));
497  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
498  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
499  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
500 
501  SCIPsetDebugMsg(set, "adding upper bound change info to var <%s>[%g,%g]: depth=%d, pos=%d, infer%s=<%s>, inferinfo=%d, %g -> %g\n",
502  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, depth, pos, infercons != NULL ? "cons" : "prop",
503  infercons != NULL ? SCIPconsGetName(infercons) : (inferprop != NULL ? SCIPpropGetName(inferprop) : "-"), inferinfo,
504  oldbound, newbound);
505 
506  SCIP_CALL( varEnsureUbchginfosSize(var, blkmem, set, var->nubchginfos+1) );
507  var->ubchginfos[var->nubchginfos].oldbound = oldbound;
508  var->ubchginfos[var->nubchginfos].newbound = newbound;
509  var->ubchginfos[var->nubchginfos].var = var;
510  var->ubchginfos[var->nubchginfos].bdchgidx.depth = depth;
511  var->ubchginfos[var->nubchginfos].bdchgidx.pos = pos;
512  var->ubchginfos[var->nubchginfos].pos = var->nubchginfos; /*lint !e732*/
513  var->ubchginfos[var->nubchginfos].boundchgtype = boundchgtype; /*lint !e641*/
514  var->ubchginfos[var->nubchginfos].boundtype = SCIP_BOUNDTYPE_UPPER; /*lint !e641*/
515  var->ubchginfos[var->nubchginfos].redundant = FALSE;
516  var->ubchginfos[var->nubchginfos].inferboundtype = inferboundtype; /*lint !e641*/
517  var->ubchginfos[var->nubchginfos].inferencedata.var = infervar;
518  var->ubchginfos[var->nubchginfos].inferencedata.info = inferinfo;
519 
520  /**@note The "pos" data member of the bound change info has a size of 27 bits */
521  assert(var->nubchginfos < 1 << 27);
522 
523  switch( boundchgtype )
524  {
526  break;
528  assert(infercons != NULL);
529  var->ubchginfos[var->nubchginfos].inferencedata.reason.cons = infercons;
530  break;
532  var->ubchginfos[var->nubchginfos].inferencedata.reason.prop = inferprop;
533  break;
534  default:
535  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
536  return SCIP_INVALIDDATA;
537  }
538 
539  var->nubchginfos++;
540 
541  assert(var->nubchginfos < 2
543  &var->ubchginfos[var->nubchginfos-1].bdchgidx));
544 
545  return SCIP_OKAY;
546 }
547 
548 /** applies single bound change */
550  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
551  BMS_BLKMEM* blkmem, /**< block memory */
552  SCIP_SET* set, /**< global SCIP settings */
553  SCIP_STAT* stat, /**< problem statistics */
554  SCIP_LP* lp, /**< current LP data */
555  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
556  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
557  int depth, /**< depth in the tree, where the bound change takes place */
558  int pos, /**< position of the bound change in its bound change array */
559  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
560  )
561 {
562  SCIP_VAR* var;
563 
564  assert(boundchg != NULL);
565  assert(stat != NULL);
566  assert(depth > 0);
567  assert(pos >= 0);
568  assert(cutoff != NULL);
569 
570  *cutoff = FALSE;
571 
572  /* ignore redundant bound changes */
573  if( boundchg->redundant )
574  return SCIP_OKAY;
575 
576  var = boundchg->var;
577  assert(var != NULL);
579  assert(!SCIPvarIsIntegral(var) || SCIPsetIsIntegral(set, boundchg->newbound));
580 
581  /* apply bound change */
582  switch( boundchg->boundtype )
583  {
585  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
586  if( SCIPsetIsGT(set, boundchg->newbound, var->locdom.lb) )
587  {
588  if( SCIPsetIsLE(set, boundchg->newbound, var->locdom.ub) )
589  {
590  /* add the bound change info to the variable's bound change info array */
591  switch( boundchg->boundchgtype )
592  {
594  SCIPsetDebugMsg(set, " -> branching: new lower bound of <%s>[%g,%g]: %g\n",
595  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
596  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
598  stat->lastbranchvar = var;
600  stat->lastbranchvalue = boundchg->newbound;
601  break;
602 
604  assert(boundchg->data.inferencedata.reason.cons != NULL);
605  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
606  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
607  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
608  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
609  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
610  boundchg->data.inferencedata.info,
612  break;
613 
615  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new lower bound of <%s>[%g,%g]: %g\n",
616  boundchg->data.inferencedata.reason.prop != NULL
617  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
618  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
619  SCIP_CALL( varAddLbchginfo(var, blkmem, set, var->locdom.lb, boundchg->newbound, depth, pos,
620  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
621  boundchg->data.inferencedata.info,
623  break;
624 
625  default:
626  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
627  return SCIP_INVALIDDATA;
628  }
629 
630  /* change local bound of variable */
631  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
632  }
633  else
634  {
635  SCIPsetDebugMsg(set, " -> cutoff: new lower bound of <%s>[%g,%g]: %g\n",
636  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
637  *cutoff = TRUE;
638  boundchg->redundant = TRUE; /* bound change has not entered the lbchginfos array of the variable! */
639  }
640  }
641  else
642  {
643  /* mark bound change to be inactive */
644  SCIPsetDebugMsg(set, " -> inactive %s: new lower bound of <%s>[%g,%g]: %g\n",
645  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
646  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
647  boundchg->redundant = TRUE;
648  }
649  break;
650 
652  /* check, if the bound change is still active (could be replaced by inference due to repropagation of higher node) */
653  if( SCIPsetIsLT(set, boundchg->newbound, var->locdom.ub) )
654  {
655  if( SCIPsetIsGE(set, boundchg->newbound, var->locdom.lb) )
656  {
657  /* add the bound change info to the variable's bound change info array */
658  switch( boundchg->boundchgtype )
659  {
661  SCIPsetDebugMsg(set, " -> branching: new upper bound of <%s>[%g,%g]: %g\n",
662  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
663  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
665  stat->lastbranchvar = var;
667  stat->lastbranchvalue = boundchg->newbound;
668  break;
669 
671  assert(boundchg->data.inferencedata.reason.cons != NULL);
672  SCIPsetDebugMsg(set, " -> constraint <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
673  SCIPconsGetName(boundchg->data.inferencedata.reason.cons),
674  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
675  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
676  boundchg->data.inferencedata.var, boundchg->data.inferencedata.reason.cons, NULL,
677  boundchg->data.inferencedata.info,
679  break;
680 
682  SCIPsetDebugMsg(set, " -> propagator <%s> inference: new upper bound of <%s>[%g,%g]: %g\n",
683  boundchg->data.inferencedata.reason.prop != NULL
684  ? SCIPpropGetName(boundchg->data.inferencedata.reason.prop) : "-",
685  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
686  SCIP_CALL( varAddUbchginfo(var, blkmem, set, var->locdom.ub, boundchg->newbound, depth, pos,
687  boundchg->data.inferencedata.var, NULL, boundchg->data.inferencedata.reason.prop,
688  boundchg->data.inferencedata.info,
690  break;
691 
692  default:
693  SCIPerrorMessage("invalid bound change type %d\n", boundchg->boundchgtype);
694  return SCIP_INVALIDDATA;
695  }
696 
697  /* change local bound of variable */
698  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, boundchg->newbound) );
699  }
700  else
701  {
702  SCIPsetDebugMsg(set, " -> cutoff: new upper bound of <%s>[%g,%g]: %g\n",
703  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
704  *cutoff = TRUE;
705  boundchg->redundant = TRUE; /* bound change has not entered the ubchginfos array of the variable! */
706  }
707  }
708  else
709  {
710  /* mark bound change to be inactive */
711  SCIPsetDebugMsg(set, " -> inactive %s: new upper bound of <%s>[%g,%g]: %g\n",
712  (SCIP_BOUNDCHGTYPE)boundchg->boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
713  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub, boundchg->newbound);
714  boundchg->redundant = TRUE;
715  }
716  break;
717 
718  default:
719  SCIPerrorMessage("unknown bound type\n");
720  return SCIP_INVALIDDATA;
721  }
722 
723  /* update the branching and inference history */
724  if( !boundchg->applied && !boundchg->redundant )
725  {
726  assert(var == boundchg->var);
727 
729  {
730  SCIP_CALL( SCIPvarIncNBranchings(var, blkmem, set, stat,
733  }
734  else if( stat->lastbranchvar != NULL )
735  {
736  /**@todo if last branching variable is unknown, retrieve it from the nodes' boundchg arrays */
737  SCIP_CALL( SCIPvarIncInferenceSum(stat->lastbranchvar, blkmem, set, stat, stat->lastbranchdir, stat->lastbranchvalue, 1.0) );
738  }
739  boundchg->applied = TRUE;
740  }
741 
742  return SCIP_OKAY;
743 }
744 
745 /** undoes single bound change */
747  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
748  BMS_BLKMEM* blkmem, /**< block memory */
749  SCIP_SET* set, /**< global SCIP settings */
750  SCIP_STAT* stat, /**< problem statistics */
751  SCIP_LP* lp, /**< current LP data */
752  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
753  SCIP_EVENTQUEUE* eventqueue /**< event queue */
754  )
755 {
756  SCIP_VAR* var;
757 
758  assert(boundchg != NULL);
759  assert(stat != NULL);
760 
761  /* ignore redundant bound changes */
762  if( boundchg->redundant )
763  return SCIP_OKAY;
764 
765  var = boundchg->var;
766  assert(var != NULL);
768 
769  /* undo bound change: apply the previous bound change of variable */
770  switch( boundchg->boundtype )
771  {
773  var->nlbchginfos--;
774  assert(var->nlbchginfos >= 0);
775  assert(var->lbchginfos != NULL);
776  assert( SCIPsetIsFeasEQ(set, var->lbchginfos[var->nlbchginfos].newbound, var->locdom.lb) ); /*lint !e777*/
777  assert( SCIPsetIsFeasLE(set, boundchg->newbound, var->locdom.lb) ); /* current lb might be larger to intermediate global bound change */
778 
779  SCIPsetDebugMsg(set, "removed lower bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
780  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
783 
784  /* reinstall the previous local bound */
785  SCIP_CALL( SCIPvarChgLbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
786  var->lbchginfos[var->nlbchginfos].oldbound) );
787 
788  /* in case all bound changes are removed the local bound should match the global bound */
789  assert(var->nlbchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.lb, var->glbdom.lb));
790 
791  break;
792 
794  var->nubchginfos--;
795  assert(var->nubchginfos >= 0);
796  assert(var->ubchginfos != NULL);
797  assert( SCIPsetIsFeasEQ(set, var->ubchginfos[var->nubchginfos].newbound, var->locdom.ub) ); /*lint !e777*/
798  assert( SCIPsetIsFeasGE(set, boundchg->newbound, var->locdom.ub) ); /* current ub might be smaller to intermediate global bound change */
799 
800  SCIPsetDebugMsg(set, "removed upper bound change info of var <%s>[%g,%g]: depth=%d, pos=%d, %g -> %g\n",
801  SCIPvarGetName(var), var->locdom.lb, var->locdom.ub,
804 
805  /* reinstall the previous local bound */
806  SCIP_CALL( SCIPvarChgUbLocal(boundchg->var, blkmem, set, stat, lp, branchcand, eventqueue,
807  var->ubchginfos[var->nubchginfos].oldbound) );
808 
809  /* in case all bound changes are removed the local bound should match the global bound */
810  assert(var->nubchginfos > 0 || SCIPsetIsFeasEQ(set, var->locdom.ub, var->glbdom.ub));
811 
812  break;
813 
814  default:
815  SCIPerrorMessage("unknown bound type\n");
816  return SCIP_INVALIDDATA;
817  }
818 
819  /* update last branching variable */
821  {
822  stat->lastbranchvar = NULL;
824  }
825 
826  return SCIP_OKAY;
827 }
828 
829 /** applies single bound change to the global problem by changing the global bound of the corresponding variable */
830 static
832  SCIP_BOUNDCHG* boundchg, /**< bound change to apply */
833  BMS_BLKMEM* blkmem, /**< block memory */
834  SCIP_SET* set, /**< global SCIP settings */
835  SCIP_STAT* stat, /**< problem statistics */
836  SCIP_LP* lp, /**< current LP data */
837  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
838  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
839  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
840  SCIP_Bool* cutoff /**< pointer to store whether an infeasible bound change was detected */
841  )
842 {
843  SCIP_VAR* var;
844  SCIP_Real newbound;
845  SCIP_BOUNDTYPE boundtype;
846 
847  assert(boundchg != NULL);
848  assert(cutoff != NULL);
849 
850  *cutoff = FALSE;
851 
852  /* ignore redundant bound changes */
853  if( boundchg->redundant )
854  return SCIP_OKAY;
855 
856  var = SCIPboundchgGetVar(boundchg);
857  newbound = SCIPboundchgGetNewbound(boundchg);
858  boundtype = SCIPboundchgGetBoundtype(boundchg);
859 
860  /* check if the bound change is redundant which can happen due to a (better) global bound change which was performed
861  * after that bound change was applied
862  *
863  * @note a global bound change is not captured by the redundant member of the bound change data structure
864  */
865  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasLE(set, newbound, SCIPvarGetLbGlobal(var)))
866  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasGE(set, newbound, SCIPvarGetUbGlobal(var))) )
867  {
868  return SCIP_OKAY;
869  }
870 
871  SCIPsetDebugMsg(set, "applying global bound change: <%s>[%g,%g] %s %g\n",
873  boundtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", newbound);
874 
875  /* check for cutoff */
876  if( (boundtype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, newbound, SCIPvarGetUbGlobal(var)))
877  || (boundtype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, newbound, SCIPvarGetLbGlobal(var))) )
878  {
879  *cutoff = TRUE;
880  return SCIP_OKAY;
881  }
882 
883  /* apply bound change */
884  SCIP_CALL( SCIPvarChgBdGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound, boundtype) );
885 
886  return SCIP_OKAY;
887 }
888 
889 /** captures branching and inference data of bound change */
890 static
892  SCIP_BOUNDCHG* boundchg /**< bound change to remove */
893  )
894 {
895  assert(boundchg != NULL);
896 
897  /* capture variable associated with the bound change */
898  assert(boundchg->var != NULL);
899  SCIPvarCapture(boundchg->var);
900 
901  switch( boundchg->boundchgtype )
902  {
905  break;
906 
908  assert(boundchg->data.inferencedata.var != NULL);
909  assert(boundchg->data.inferencedata.reason.cons != NULL);
910  SCIPconsCapture(boundchg->data.inferencedata.reason.cons);
911  break;
912 
913  default:
914  SCIPerrorMessage("invalid bound change type\n");
915  return SCIP_INVALIDDATA;
916  }
917 
918  return SCIP_OKAY;
919 }
920 
921 /** releases branching and inference data of bound change */
922 static
924  SCIP_BOUNDCHG* boundchg, /**< bound change to remove */
925  BMS_BLKMEM* blkmem, /**< block memory */
926  SCIP_SET* set, /**< global SCIP settings */
927  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
928  SCIP_LP* lp /**< current LP data */
929 
930  )
931 {
932  assert(boundchg != NULL);
933 
934  switch( boundchg->boundchgtype )
935  {
938  break;
939 
941  assert(boundchg->data.inferencedata.var != NULL);
942  assert(boundchg->data.inferencedata.reason.cons != NULL);
943  SCIP_CALL( SCIPconsRelease(&boundchg->data.inferencedata.reason.cons, blkmem, set) );
944  break;
945 
946  default:
947  SCIPerrorMessage("invalid bound change type\n");
948  return SCIP_INVALIDDATA;
949  }
950 
951  /* release variable */
952  assert(boundchg->var != NULL);
953  SCIP_CALL( SCIPvarRelease(&boundchg->var, blkmem, set, eventqueue, lp) );
954 
955 
956  return SCIP_OKAY;
957 }
958 
959 /** creates empty domain change data with dynamic arrays */
960 static
962  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
963  BMS_BLKMEM* blkmem /**< block memory */
964  )
965 {
966  assert(domchg != NULL);
967  assert(blkmem != NULL);
968 
969  SCIP_ALLOC( BMSallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN)) );
970  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
971  (*domchg)->domchgdyn.nboundchgs = 0;
972  (*domchg)->domchgdyn.boundchgs = NULL;
973  (*domchg)->domchgdyn.nholechgs = 0;
974  (*domchg)->domchgdyn.holechgs = NULL;
975  (*domchg)->domchgdyn.boundchgssize = 0;
976  (*domchg)->domchgdyn.holechgssize = 0;
977 
978  return SCIP_OKAY;
979 }
980 
981 /** frees domain change data */
983  SCIP_DOMCHG** domchg, /**< pointer to domain change */
984  BMS_BLKMEM* blkmem, /**< block memory */
985  SCIP_SET* set, /**< global SCIP settings */
986  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
987  SCIP_LP* lp /**< current LP data */
988  )
989 {
990  assert(domchg != NULL);
991  assert(blkmem != NULL);
992 
993  if( *domchg != NULL )
994  {
995  int i;
996 
997  /* release variables, branching and inference data associated with the bound changes */
998  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
999  {
1000  SCIP_CALL( boundchgReleaseData(&(*domchg)->domchgbound.boundchgs[i], blkmem, set, eventqueue, lp) );
1001  }
1002 
1003  /* free memory for bound and hole changes */
1004  switch( (*domchg)->domchgdyn.domchgtype )
1005  {
1006  case SCIP_DOMCHGTYPE_BOUND:
1007  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgbound.boundchgs, (*domchg)->domchgbound.nboundchgs);
1008  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND));
1009  break;
1010  case SCIP_DOMCHGTYPE_BOTH:
1011  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.boundchgs, (*domchg)->domchgboth.nboundchgs);
1012  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgboth.holechgs, (*domchg)->domchgboth.nholechgs);
1013  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH));
1014  break;
1016  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.boundchgs, (*domchg)->domchgdyn.boundchgssize);
1017  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1018  BMSfreeBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN));
1019  break;
1020  default:
1021  SCIPerrorMessage("invalid domain change type\n");
1022  return SCIP_INVALIDDATA;
1023  }
1024  }
1025 
1026  return SCIP_OKAY;
1027 }
1028 
1029 /** converts a static domain change data into a dynamic one */
1030 static
1032  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1033  BMS_BLKMEM* blkmem /**< block memory */
1034  )
1035 {
1036  assert(domchg != NULL);
1037  assert(blkmem != NULL);
1038 
1039  SCIPdebugMessage("making domain change data %p pointing to %p dynamic\n", (void*)domchg, (void*)*domchg);
1040 
1041  if( *domchg == NULL )
1042  {
1043  SCIP_CALL( domchgCreate(domchg, blkmem) );
1044  }
1045  else
1046  {
1047  switch( (*domchg)->domchgdyn.domchgtype )
1048  {
1049  case SCIP_DOMCHGTYPE_BOUND:
1050  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOUND), sizeof(SCIP_DOMCHGDYN)) );
1051  (*domchg)->domchgdyn.nholechgs = 0;
1052  (*domchg)->domchgdyn.holechgs = NULL;
1053  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1054  (*domchg)->domchgdyn.holechgssize = 0;
1055  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1056  break;
1057  case SCIP_DOMCHGTYPE_BOTH:
1058  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGDYN)) );
1059  (*domchg)->domchgdyn.boundchgssize = (*domchg)->domchgdyn.nboundchgs;
1060  (*domchg)->domchgdyn.holechgssize = (*domchg)->domchgdyn.nholechgs;
1061  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_DYNAMIC; /*lint !e641*/
1062  break;
1064  break;
1065  default:
1066  SCIPerrorMessage("invalid domain change type\n");
1067  return SCIP_INVALIDDATA;
1068  }
1069  }
1070 #ifndef NDEBUG
1071  {
1072  int i;
1073  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1074  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1075  || EPSISINT((*domchg)->domchgbound.boundchgs[i].newbound, 1e-06));
1076  }
1077 #endif
1078 
1079  return SCIP_OKAY;
1080 }
1081 
1082 /** converts a dynamic domain change data into a static one, using less memory than for a dynamic one */
1084  SCIP_DOMCHG** domchg, /**< pointer to domain change data */
1085  BMS_BLKMEM* blkmem, /**< block memory */
1086  SCIP_SET* set, /**< global SCIP settings */
1087  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1088  SCIP_LP* lp /**< current LP data */
1089  )
1090 {
1091  assert(domchg != NULL);
1092  assert(blkmem != NULL);
1093 
1094  SCIPsetDebugMsg(set, "making domain change data %p pointing to %p static\n", (void*)domchg, (void*)*domchg);
1095 
1096  if( *domchg != NULL )
1097  {
1098  switch( (*domchg)->domchgdyn.domchgtype )
1099  {
1100  case SCIP_DOMCHGTYPE_BOUND:
1101  if( (*domchg)->domchgbound.nboundchgs == 0 )
1102  {
1103  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1104  }
1105  break;
1106  case SCIP_DOMCHGTYPE_BOTH:
1107  if( (*domchg)->domchgboth.nholechgs == 0 )
1108  {
1109  if( (*domchg)->domchgbound.nboundchgs == 0 )
1110  {
1111  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1112  }
1113  else
1114  {
1115  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGBOTH), sizeof(SCIP_DOMCHGBOUND)) );
1116  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1117  }
1118  }
1119  break;
1121  if( (*domchg)->domchgboth.nholechgs == 0 )
1122  {
1123  if( (*domchg)->domchgbound.nboundchgs == 0 )
1124  {
1125  SCIP_CALL( SCIPdomchgFree(domchg, blkmem, set, eventqueue, lp) );
1126  }
1127  else
1128  {
1129  /* shrink dynamic size arrays to their minimal sizes */
1130  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1131  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1132  BMSfreeBlockMemoryArrayNull(blkmem, &(*domchg)->domchgdyn.holechgs, (*domchg)->domchgdyn.holechgssize);
1133 
1134  /* convert into static domain change */
1135  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOUND)) );
1136  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOUND; /*lint !e641*/
1137  }
1138  }
1139  else
1140  {
1141  /* shrink dynamic size arrays to their minimal sizes */
1142  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.boundchgs,
1143  (*domchg)->domchgdyn.boundchgssize, (*domchg)->domchgdyn.nboundchgs) ); /*lint !e571*/
1144  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(*domchg)->domchgdyn.holechgs,
1145  (*domchg)->domchgdyn.holechgssize, (*domchg)->domchgdyn.nholechgs) );
1146 
1147  /* convert into static domain change */
1148  SCIP_ALLOC( BMSreallocBlockMemorySize(blkmem, domchg, sizeof(SCIP_DOMCHGDYN), sizeof(SCIP_DOMCHGBOTH)) );
1149  (*domchg)->domchgdyn.domchgtype = SCIP_DOMCHGTYPE_BOTH; /*lint !e641*/
1150  }
1151  break;
1152  default:
1153  SCIPerrorMessage("invalid domain change type\n");
1154  return SCIP_INVALIDDATA;
1155  }
1156 #ifndef NDEBUG
1157  if( *domchg != NULL )
1158  {
1159  int i;
1160  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1161  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1162  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1163  }
1164 #endif
1165  }
1166 
1167  return SCIP_OKAY;
1168 }
1169 
1170 /** ensures, that boundchgs array can store at least num entries */
1171 static
1173  SCIP_DOMCHG* domchg, /**< domain change data structure */
1174  BMS_BLKMEM* blkmem, /**< block memory */
1175  SCIP_SET* set, /**< global SCIP settings */
1176  int num /**< minimum number of entries to store */
1177  )
1178 {
1179  assert(domchg != NULL);
1180  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1181 
1182  if( num > domchg->domchgdyn.boundchgssize )
1183  {
1184  int newsize;
1185 
1186  newsize = SCIPsetCalcMemGrowSize(set, num);
1187  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.boundchgs, domchg->domchgdyn.boundchgssize, newsize) );
1188  domchg->domchgdyn.boundchgssize = newsize;
1189  }
1190  assert(num <= domchg->domchgdyn.boundchgssize);
1191 
1192  return SCIP_OKAY;
1193 }
1194 
1195 /** ensures, that holechgs array can store at least num additional entries */
1196 static
1198  SCIP_DOMCHG* domchg, /**< domain change data structure */
1199  BMS_BLKMEM* blkmem, /**< block memory */
1200  SCIP_SET* set, /**< global SCIP settings */
1201  int num /**< minimum number of additional entries to store */
1202  )
1203 {
1204  assert(domchg != NULL);
1205  assert(domchg->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1206 
1207  if( num > domchg->domchgdyn.holechgssize )
1208  {
1209  int newsize;
1210 
1211  newsize = SCIPsetCalcMemGrowSize(set, num);
1212  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &domchg->domchgdyn.holechgs, domchg->domchgdyn.holechgssize, newsize) );
1213  domchg->domchgdyn.holechgssize = newsize;
1214  }
1215  assert(num <= domchg->domchgdyn.holechgssize);
1216 
1217  return SCIP_OKAY;
1218 }
1219 
1220 /** applies domain change */
1222  SCIP_DOMCHG* domchg, /**< domain change to apply */
1223  BMS_BLKMEM* blkmem, /**< block memory */
1224  SCIP_SET* set, /**< global SCIP settings */
1225  SCIP_STAT* stat, /**< problem statistics */
1226  SCIP_LP* lp, /**< current LP data */
1227  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1228  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1229  int depth, /**< depth in the tree, where the domain change takes place */
1230  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1231  )
1232 {
1233  int i;
1234 
1235  assert(cutoff != NULL);
1236 
1237  *cutoff = FALSE;
1238 
1239  SCIPsetDebugMsg(set, "applying domain changes at %p in depth %d\n", (void*)domchg, depth);
1240 
1241  if( domchg == NULL )
1242  return SCIP_OKAY;
1243 
1244  /* apply bound changes */
1245  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1246  {
1247  SCIP_CALL( SCIPboundchgApply(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1248  branchcand, eventqueue, depth, i, cutoff) );
1249  if( *cutoff )
1250  break;
1251  }
1252  SCIPsetDebugMsg(set, " -> %u bound changes (cutoff %u)\n", domchg->domchgbound.nboundchgs, *cutoff);
1253 
1254  /* mark all bound changes after a cutoff redundant */
1255  for( ; i < (int)domchg->domchgbound.nboundchgs; ++i )
1256  domchg->domchgbound.boundchgs[i].redundant = TRUE;
1257 
1258  /* apply holelist changes */
1259  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1260  {
1261  for( i = 0; i < domchg->domchgboth.nholechgs; ++i )
1262  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].newlist;
1263  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1264  }
1265 
1266  return SCIP_OKAY;
1267 }
1268 
1269 /** undoes domain change */
1271  SCIP_DOMCHG* domchg, /**< domain change to remove */
1272  BMS_BLKMEM* blkmem, /**< block memory */
1273  SCIP_SET* set, /**< global SCIP settings */
1274  SCIP_STAT* stat, /**< problem statistics */
1275  SCIP_LP* lp, /**< current LP data */
1276  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1277  SCIP_EVENTQUEUE* eventqueue /**< event queue */
1278  )
1279 {
1280  int i;
1281 
1282  SCIPsetDebugMsg(set, "undoing domain changes at %p\n", (void*)domchg);
1283  if( domchg == NULL )
1284  return SCIP_OKAY;
1285 
1286  /* undo holelist changes */
1287  if( domchg->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_BOUND ) /*lint !e641*/
1288  {
1289  for( i = domchg->domchgboth.nholechgs-1; i >= 0; --i )
1290  *(domchg->domchgboth.holechgs[i].ptr) = domchg->domchgboth.holechgs[i].oldlist;
1291  SCIPsetDebugMsg(set, " -> %d hole changes\n", domchg->domchgboth.nholechgs);
1292  }
1293 
1294  /* undo bound changes */
1295  for( i = domchg->domchgbound.nboundchgs-1; i >= 0; --i )
1296  {
1297  SCIP_CALL( SCIPboundchgUndo(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp, branchcand, eventqueue) );
1298  }
1299  SCIPsetDebugMsg(set, " -> %u bound changes\n", domchg->domchgbound.nboundchgs);
1300 
1301  return SCIP_OKAY;
1302 }
1303 
1304 /** applies domain change to the global problem */
1306  SCIP_DOMCHG* domchg, /**< domain change to apply */
1307  BMS_BLKMEM* blkmem, /**< block memory */
1308  SCIP_SET* set, /**< global SCIP settings */
1309  SCIP_STAT* stat, /**< problem statistics */
1310  SCIP_LP* lp, /**< current LP data */
1311  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
1312  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
1313  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1314  SCIP_Bool* cutoff /**< pointer to store whether an infeasible domain change was detected */
1315  )
1316 {
1317  int i;
1318 
1319  assert(cutoff != NULL);
1320 
1321  *cutoff = FALSE;
1322 
1323  if( domchg == NULL )
1324  return SCIP_OKAY;
1325 
1326  SCIPsetDebugMsg(set, "applying domain changes at %p to the global problem\n", (void*)domchg);
1327 
1328  /* apply bound changes */
1329  for( i = 0; i < (int)domchg->domchgbound.nboundchgs; ++i )
1330  {
1331  SCIP_CALL( boundchgApplyGlobal(&domchg->domchgbound.boundchgs[i], blkmem, set, stat, lp,
1332  branchcand, eventqueue, cliquetable, cutoff) );
1333  if( *cutoff )
1334  break;
1335  }
1336  SCIPsetDebugMsg(set, " -> %u global bound changes\n", domchg->domchgbound.nboundchgs);
1337 
1338  /**@todo globally apply holelist changes - how can this be done without confusing pointer updates? */
1339 
1340  return SCIP_OKAY;
1341 }
1342 
1343 /** adds bound change to domain changes */
1345  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1346  BMS_BLKMEM* blkmem, /**< block memory */
1347  SCIP_SET* set, /**< global SCIP settings */
1348  SCIP_VAR* var, /**< variable to change the bounds for */
1349  SCIP_Real newbound, /**< new value for bound */
1350  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
1351  SCIP_BOUNDCHGTYPE boundchgtype, /**< type of bound change: branching decision or inference */
1352  SCIP_Real lpsolval, /**< solval of variable in last LP on path to node, or SCIP_INVALID if unknown */
1353  SCIP_VAR* infervar, /**< variable that was changed (parent of var, or var itself), or NULL */
1354  SCIP_CONS* infercons, /**< constraint that deduced the bound change, or NULL */
1355  SCIP_PROP* inferprop, /**< propagator that deduced the bound change, or NULL */
1356  int inferinfo, /**< user information for inference to help resolving the conflict */
1357  SCIP_BOUNDTYPE inferboundtype /**< type of bound for inference var: lower or upper bound */
1358  )
1359 {
1360  SCIP_BOUNDCHG* boundchg;
1361 
1362  assert(domchg != NULL);
1363  assert(var != NULL);
1365  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
1366  assert(!SCIPvarIsBinary(var) || SCIPsetIsEQ(set, newbound, boundtype == SCIP_BOUNDTYPE_LOWER ? 1.0 : 0.0));
1367  assert(boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING || infervar != NULL);
1368  assert((boundchgtype == SCIP_BOUNDCHGTYPE_CONSINFER) == (infercons != NULL));
1369  assert(boundchgtype == SCIP_BOUNDCHGTYPE_PROPINFER || inferprop == NULL);
1370 
1371  SCIPsetDebugMsg(set, "adding %s bound change <%s: %g> of variable <%s> to domain change at %p pointing to %p\n",
1372  boundtype == SCIP_BOUNDTYPE_LOWER ? "lower" : "upper", boundchgtype == SCIP_BOUNDCHGTYPE_BRANCHING ? "branching" : "inference",
1373  newbound, var->name, (void*)domchg, (void*)*domchg);
1374 
1375  /* if domain change data doesn't exist, create it;
1376  * if domain change is static, convert it into dynamic change
1377  */
1378  if( *domchg == NULL )
1379  {
1380  SCIP_CALL( domchgCreate(domchg, blkmem) );
1381  }
1382  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1383  {
1384  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1385  }
1386  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1387 
1388  /* get memory for additional bound change */
1389  SCIP_CALL( domchgEnsureBoundchgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nboundchgs+1) );
1390 
1391  /* fill in the bound change data */
1392  boundchg = &(*domchg)->domchgdyn.boundchgs[(*domchg)->domchgdyn.nboundchgs];
1393  boundchg->var = var;
1394  switch( boundchgtype )
1395  {
1397  boundchg->data.branchingdata.lpsolval = lpsolval;
1398  break;
1400  assert(infercons != NULL);
1401  boundchg->data.inferencedata.var = infervar;
1402  boundchg->data.inferencedata.reason.cons = infercons;
1403  boundchg->data.inferencedata.info = inferinfo;
1404  break;
1406  boundchg->data.inferencedata.var = infervar;
1407  boundchg->data.inferencedata.reason.prop = inferprop;
1408  boundchg->data.inferencedata.info = inferinfo;
1409  break;
1410  default:
1411  SCIPerrorMessage("invalid bound change type %d\n", boundchgtype);
1412  return SCIP_INVALIDDATA;
1413  }
1414 
1415  boundchg->newbound = newbound;
1416  boundchg->boundchgtype = boundchgtype; /*lint !e641*/
1417  boundchg->boundtype = boundtype; /*lint !e641*/
1418  boundchg->inferboundtype = inferboundtype; /*lint !e641*/
1419  boundchg->applied = FALSE;
1420  boundchg->redundant = FALSE;
1421  (*domchg)->domchgdyn.nboundchgs++;
1422 
1423  /* capture branching and inference data associated with the bound changes */
1424  SCIP_CALL( boundchgCaptureData(boundchg) );
1425 
1426 #ifdef SCIP_DISABLED_CODE /* expensive debug check */
1427 #ifdef SCIP_MORE_DEBUG
1428  {
1429  int i;
1430  for( i = 0; i < (int)(*domchg)->domchgbound.nboundchgs; ++i )
1431  assert(SCIPvarGetType((*domchg)->domchgbound.boundchgs[i].var) == SCIP_VARTYPE_CONTINUOUS
1432  || SCIPsetIsFeasIntegral(set, (*domchg)->domchgbound.boundchgs[i].newbound));
1433  }
1434 #endif
1435 #endif
1436 
1437  return SCIP_OKAY;
1438 }
1439 
1440 /** adds hole change to domain changes */
1442  SCIP_DOMCHG** domchg, /**< pointer to domain change data structure */
1443  BMS_BLKMEM* blkmem, /**< block memory */
1444  SCIP_SET* set, /**< global SCIP settings */
1445  SCIP_HOLELIST** ptr, /**< changed list pointer */
1446  SCIP_HOLELIST* newlist, /**< new value of list pointer */
1447  SCIP_HOLELIST* oldlist /**< old value of list pointer */
1448  )
1449 {
1450  SCIP_HOLECHG* holechg;
1451 
1452  assert(domchg != NULL);
1453  assert(ptr != NULL);
1454 
1455  /* if domain change data doesn't exist, create it;
1456  * if domain change is static, convert it into dynamic change
1457  */
1458  if( *domchg == NULL )
1459  {
1460  SCIP_CALL( domchgCreate(domchg, blkmem) );
1461  }
1462  else if( (*domchg)->domchgdyn.domchgtype != SCIP_DOMCHGTYPE_DYNAMIC ) /*lint !e641*/
1463  {
1464  SCIP_CALL( domchgMakeDynamic(domchg, blkmem) );
1465  }
1466  assert(*domchg != NULL && (*domchg)->domchgdyn.domchgtype == SCIP_DOMCHGTYPE_DYNAMIC); /*lint !e641*/
1467 
1468  /* get memory for additional hole change */
1469  SCIP_CALL( domchgEnsureHolechgsSize(*domchg, blkmem, set, (*domchg)->domchgdyn.nholechgs+1) );
1470 
1471  /* fill in the hole change data */
1472  holechg = &(*domchg)->domchgdyn.holechgs[(*domchg)->domchgdyn.nholechgs];
1473  holechg->ptr = ptr;
1474  holechg->newlist = newlist;
1475  holechg->oldlist = oldlist;
1476  (*domchg)->domchgdyn.nholechgs++;
1477 
1478  return SCIP_OKAY;
1479 }
1480 
1481 
1482 
1483 
1484 /*
1485  * methods for variables
1486  */
1487 
1488 /** returns adjusted lower bound value, which is rounded for integral variable types */
1489 static
1491  SCIP_SET* set, /**< global SCIP settings */
1492  SCIP_VARTYPE vartype, /**< type of variable */
1493  SCIP_Real lb /**< lower bound to adjust */
1494  )
1495 {
1496  if( lb < 0 && SCIPsetIsInfinity(set, -lb) )
1497  return -SCIPsetInfinity(set);
1498  else if( lb > 0 && SCIPsetIsInfinity(set, lb) )
1499  return SCIPsetInfinity(set);
1500  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1501  return SCIPsetFeasCeil(set, lb);
1502  else if( SCIPsetIsZero(set, lb) )
1503  return 0.0;
1504  else
1505  return lb;
1506 }
1507 
1508 /** returns adjusted upper bound value, which is rounded for integral variable types */
1509 static
1511  SCIP_SET* set, /**< global SCIP settings */
1512  SCIP_VARTYPE vartype, /**< type of variable */
1513  SCIP_Real ub /**< upper bound to adjust */
1514  )
1515 {
1516  if( ub > 0 && SCIPsetIsInfinity(set, ub) )
1517  return SCIPsetInfinity(set);
1518  else if( ub < 0 && SCIPsetIsInfinity(set, -ub) )
1519  return -SCIPsetInfinity(set);
1520  else if( vartype != SCIP_VARTYPE_CONTINUOUS )
1521  return SCIPsetFeasFloor(set, ub);
1522  else if( SCIPsetIsZero(set, ub) )
1523  return 0.0;
1524  else
1525  return ub;
1526 }
1527 
1528 /** removes (redundant) cliques, implications and variable bounds of variable from all other variables' implications and variable
1529  * bounds arrays, and optionally removes them also from the variable itself
1530  */
1532  SCIP_VAR* var, /**< problem variable */
1533  BMS_BLKMEM* blkmem, /**< block memory */
1534  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
1535  SCIP_SET* set, /**< global SCIP settings */
1536  SCIP_Bool irrelevantvar, /**< has the variable become irrelevant? */
1537  SCIP_Bool onlyredundant, /**< should only the redundant implications and variable bounds be removed? */
1538  SCIP_Bool removefromvar /**< should the implications and variable bounds be removed from the var itself? */
1539  )
1540 {
1541  SCIP_Real lb;
1542  SCIP_Real ub;
1543 
1544  assert(var != NULL);
1546  assert(SCIPvarIsActive(var) || SCIPvarGetType(var) != SCIP_VARTYPE_BINARY);
1547 
1548  lb = SCIPvarGetLbGlobal(var);
1549  ub = SCIPvarGetUbGlobal(var);
1550 
1551  SCIPsetDebugMsg(set, "removing %s implications and vbounds of %s<%s>[%g,%g]\n",
1552  onlyredundant ? "redundant" : "all", irrelevantvar ? "irrelevant " : "", SCIPvarGetName(var), lb, ub);
1553 
1554  /* remove implications of (fixed) binary variable */
1555  if( var->implics != NULL && (!onlyredundant || lb > 0.5 || ub < 0.5) )
1556  {
1557  SCIP_Bool varfixing;
1558 
1559  assert(SCIPvarIsBinary(var));
1560 
1561  varfixing = FALSE;
1562  do
1563  {
1564  SCIP_VAR** implvars;
1565  SCIP_BOUNDTYPE* impltypes;
1566  int nimpls;
1567  int i;
1568 
1569  nimpls = SCIPimplicsGetNImpls(var->implics, varfixing);
1570  implvars = SCIPimplicsGetVars(var->implics, varfixing);
1571  impltypes = SCIPimplicsGetTypes(var->implics, varfixing);
1572 
1573  for( i = 0; i < nimpls; i++ )
1574  {
1575  SCIP_VAR* implvar;
1576  SCIP_BOUNDTYPE impltype;
1577 
1578  implvar = implvars[i];
1579  impltype = impltypes[i];
1580  assert(implvar != var);
1581 
1582  /* remove for all implications z == 0 / 1 ==> x <= p / x >= p (x not binary)
1583  * the following variable bound from x's variable bounds
1584  * x <= b*z+d (z in vubs of x) , for z == 0 / 1 ==> x <= p
1585  * x >= b*z+d (z in vlbs of x) , for z == 0 / 1 ==> x >= p
1586  */
1587  if( impltype == SCIP_BOUNDTYPE_UPPER )
1588  {
1589  if( implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1590  {
1591  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> <= %g\n",
1592  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1593  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1594  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, varfixing) );
1595  implvar->closestvblpcount = -1;
1596  var->closestvblpcount = -1;
1597  }
1598  }
1599  else
1600  {
1601  if( implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1602  {
1603  SCIPsetDebugMsg(set, "deleting variable bound: <%s> == %u ==> <%s> >= %g\n",
1604  SCIPvarGetName(var), varfixing, SCIPvarGetName(implvar),
1605  SCIPimplicsGetBounds(var->implics, varfixing)[i]);
1606  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, !varfixing) );
1607  implvar->closestvblpcount = -1;
1608  var->closestvblpcount = -1;
1609  }
1610  }
1611  }
1612  varfixing = !varfixing;
1613  }
1614  while( varfixing == TRUE );
1615 
1616  if( removefromvar )
1617  {
1618  /* free the implications data structures */
1619  SCIPimplicsFree(&var->implics, blkmem);
1620  }
1621  }
1622 
1623  /* remove the (redundant) variable lower bounds */
1624  if( var->vlbs != NULL )
1625  {
1626  SCIP_VAR** vars;
1627  SCIP_Real* coefs;
1628  SCIP_Real* constants;
1629  int nvbds;
1630  int newnvbds;
1631  int i;
1632 
1633  nvbds = SCIPvboundsGetNVbds(var->vlbs);
1634  vars = SCIPvboundsGetVars(var->vlbs);
1635  coefs = SCIPvboundsGetCoefs(var->vlbs);
1636  constants = SCIPvboundsGetConstants(var->vlbs);
1637 
1638  /* remove for all variable bounds x >= b*z+d the following implication from z's implications
1639  * z == ub ==> x >= b*ub + d , if b > 0
1640  * z == lb ==> x >= b*lb + d , if b < 0
1641  */
1642  newnvbds = 0;
1643  for( i = 0; i < nvbds; i++ )
1644  {
1645  SCIP_VAR* implvar;
1646  SCIP_Real coef;
1647 
1648  assert(newnvbds <= i);
1649 
1650  implvar = vars[i];
1651  assert(implvar != NULL);
1652 
1653  coef = coefs[i];
1654  assert(!SCIPsetIsZero(set, coef));
1655 
1656  /* check, if we want to remove the variable bound */
1657  if( onlyredundant )
1658  {
1659  SCIP_Real vbound;
1660 
1661  vbound = MAX(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1662  if( SCIPsetIsFeasGT(set, vbound, lb) )
1663  {
1664  /* the variable bound is not redundant: keep it */
1665  if( removefromvar )
1666  {
1667  if( newnvbds < i )
1668  {
1669  vars[newnvbds] = implvar;
1670  coefs[newnvbds] = coef;
1671  constants[newnvbds] = constants[i];
1672  }
1673  newnvbds++;
1674  }
1675  continue;
1676  }
1677  }
1678 
1679  /* remove the corresponding implication */
1680  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1681  {
1682  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> >= %g\n",
1683  SCIPvarGetName(implvar), (coef > 0.0), SCIPvarGetName(var), MAX(coef, 0.0) + constants[i]);
1684  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef > 0.0), var, SCIP_BOUNDTYPE_LOWER) );
1685  }
1686  if( coef > 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1687  {
1688  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1689  SCIPvarGetName(implvar), SCIPvarGetName(var));
1690  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, FALSE) );
1691  implvar->closestvblpcount = -1;
1692  var->closestvblpcount = -1;
1693  }
1694  else if( coef < 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1695  {
1696  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1697  SCIPvarGetName(implvar), SCIPvarGetName(var));
1698  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, TRUE) );
1699  implvar->closestvblpcount = -1;
1700  var->closestvblpcount = -1;
1701  }
1702  }
1703 
1704  if( removefromvar )
1705  {
1706  /* update the number of variable bounds */
1707  SCIPvboundsShrink(&var->vlbs, blkmem, newnvbds);
1708  var->closestvblpcount = -1;
1709  }
1710  }
1711 
1712  /**@todo in general, variable bounds like x >= b*z + d corresponding to an implication like z = ub ==> x >= b*ub + d
1713  * might be missing because we only add variable bounds with reasonably small value of b. thus, we currently
1714  * cannot remove such variables x from z's implications.
1715  */
1716 
1717  /* remove the (redundant) variable upper bounds */
1718  if( var->vubs != NULL )
1719  {
1720  SCIP_VAR** vars;
1721  SCIP_Real* coefs;
1722  SCIP_Real* constants;
1723  int nvbds;
1724  int newnvbds;
1725  int i;
1726 
1727  nvbds = SCIPvboundsGetNVbds(var->vubs);
1728  vars = SCIPvboundsGetVars(var->vubs);
1729  coefs = SCIPvboundsGetCoefs(var->vubs);
1730  constants = SCIPvboundsGetConstants(var->vubs);
1731 
1732  /* remove for all variable bounds x <= b*z+d the following implication from z's implications
1733  * z == lb ==> x <= b*lb + d , if b > 0
1734  * z == ub ==> x <= b*ub + d , if b < 0
1735  */
1736  newnvbds = 0;
1737  for( i = 0; i < nvbds; i++ )
1738  {
1739  SCIP_VAR* implvar;
1740  SCIP_Real coef;
1741 
1742  assert(newnvbds <= i);
1743 
1744  implvar = vars[i];
1745  assert(implvar != NULL);
1746 
1747  coef = coefs[i];
1748  assert(!SCIPsetIsZero(set, coef));
1749 
1750  /* check, if we want to remove the variable bound */
1751  if( onlyredundant )
1752  {
1753  SCIP_Real vbound;
1754 
1755  vbound = MIN(coef * SCIPvarGetUbGlobal(implvar), coef * SCIPvarGetLbGlobal(implvar)) + constants[i]; /*lint !e666*/
1756  if( SCIPsetIsFeasLT(set, vbound, ub) )
1757  {
1758  /* the variable bound is not redundant: keep it */
1759  if( removefromvar )
1760  {
1761  if( newnvbds < i )
1762  {
1763  vars[newnvbds] = implvar;
1764  coefs[newnvbds] = coefs[i];
1765  constants[newnvbds] = constants[i];
1766  }
1767  newnvbds++;
1768  }
1769  continue;
1770  }
1771  }
1772 
1773  /* remove the corresponding implication */
1774  if( implvar->implics != NULL ) /* variable may have been aggregated in the mean time */
1775  {
1776  SCIPsetDebugMsg(set, "deleting implication: <%s> == %d ==> <%s> <= %g\n",
1777  SCIPvarGetName(implvar), (coef < 0.0), SCIPvarGetName(var), MIN(coef, 0.0) + constants[i]);
1778  SCIP_CALL( SCIPimplicsDel(&implvar->implics, blkmem, set, (coef < 0.0), var, SCIP_BOUNDTYPE_UPPER) );
1779  }
1780  if( coef < 0.0 && implvar->vubs != NULL ) /* implvar may have been aggregated in the mean time */
1781  {
1782  SCIPsetDebugMsg(set, "deleting variable upper bound from <%s> involving variable %s\n",
1783  SCIPvarGetName(implvar), SCIPvarGetName(var));
1784  SCIP_CALL( SCIPvboundsDel(&implvar->vubs, blkmem, var, TRUE) );
1785  implvar->closestvblpcount = -1;
1786  var->closestvblpcount = -1;
1787  }
1788  else if( coef > 0.0 && implvar->vlbs != NULL ) /* implvar may have been aggregated in the mean time */
1789  {
1790  SCIPsetDebugMsg(set, "deleting variable lower bound from <%s> involving variable %s\n",
1791  SCIPvarGetName(implvar), SCIPvarGetName(var));
1792  SCIP_CALL( SCIPvboundsDel(&implvar->vlbs, blkmem, var, FALSE) );
1793  implvar->closestvblpcount = -1;
1794  var->closestvblpcount = -1;
1795  }
1796  }
1797 
1798  if( removefromvar )
1799  {
1800  /* update the number of variable bounds */
1801  SCIPvboundsShrink(&var->vubs, blkmem, newnvbds);
1802  var->closestvblpcount = -1;
1803  }
1804  }
1805 
1806  /* remove the variable from all cliques */
1807  if( SCIPvarIsBinary(var) )
1808  {
1809  SCIPcliquelistRemoveFromCliques(var->cliquelist, cliquetable, var, irrelevantvar);
1810  SCIPcliquelistFree(&var->cliquelist, blkmem);
1811  }
1812 
1813  /**@todo variable bounds like x <= b*z + d with z general integer are not removed from x's vbd arrays, because
1814  * z has no link (like in the binary case) to x
1815  */
1816 
1817  return SCIP_OKAY;
1818 }
1819 
1820 /** sets the variable name */
1821 static
1823  SCIP_VAR* var, /**< problem variable */
1824  BMS_BLKMEM* blkmem, /**< block memory */
1825  SCIP_STAT* stat, /**< problem statistics, or NULL */
1826  const char* name /**< name of variable, or NULL for automatic name creation */
1827  )
1828 {
1829  assert(blkmem != NULL);
1830  assert(var != NULL);
1831 
1832  if( name == NULL )
1833  {
1834  char s[SCIP_MAXSTRLEN];
1835 
1836  assert(stat != NULL);
1837 
1838  (void) SCIPsnprintf(s, SCIP_MAXSTRLEN, "_var%d_", stat->nvaridx);
1839  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, s, strlen(s)+1) );
1840  }
1841  else
1842  {
1843  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->name, name, strlen(name)+1) );
1844  }
1845 
1846  return SCIP_OKAY;
1847 }
1848 
1849 
1850 /** creates variable; if variable is of integral type, fractional bounds are automatically rounded; an integer variable
1851  * with bounds zero and one is automatically converted into a binary variable
1852  */
1853 static
1855  SCIP_VAR** var, /**< pointer to variable data */
1856  BMS_BLKMEM* blkmem, /**< block memory */
1857  SCIP_SET* set, /**< global SCIP settings */
1858  SCIP_STAT* stat, /**< problem statistics */
1859  const char* name, /**< name of variable, or NULL for automatic name creation */
1860  SCIP_Real lb, /**< lower bound of variable */
1861  SCIP_Real ub, /**< upper bound of variable */
1862  SCIP_Real obj, /**< objective function value */
1863  SCIP_VARTYPE vartype, /**< type of variable */
1864  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
1865  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
1866  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
1867  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
1868  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
1869  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
1870  SCIP_VARDATA* vardata /**< user data for this specific variable */
1871  )
1872 {
1873  assert(var != NULL);
1874  assert(blkmem != NULL);
1875  assert(stat != NULL);
1876 
1877  /* adjust bounds of variable */
1878  lb = adjustedLb(set, vartype, lb);
1879  ub = adjustedUb(set, vartype, ub);
1880 
1881  /* convert [0,1]-integers into binary variables and check that binary variables have correct bounds */
1882  if( (SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0))
1883  && (SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0)) )
1884  {
1885  if( vartype == SCIP_VARTYPE_INTEGER )
1886  vartype = SCIP_VARTYPE_BINARY;
1887  }
1888  else
1889  {
1890  if( vartype == SCIP_VARTYPE_BINARY )
1891  {
1892  SCIPerrorMessage("invalid bounds [%.2g,%.2g] for binary variable <%s>\n", lb, ub, name);
1893  return SCIP_INVALIDDATA;
1894  }
1895  }
1896 
1897  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, lb, 0.0) || SCIPsetIsEQ(set, lb, 1.0));
1898  assert(vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, ub, 0.0) || SCIPsetIsEQ(set, ub, 1.0));
1899 
1900  SCIP_ALLOC( BMSallocBlockMemory(blkmem, var) );
1901 
1902  /* set variable's name */
1903  SCIP_CALL( varSetName(*var, blkmem, stat, name) );
1904 
1905 #ifndef NDEBUG
1906  (*var)->scip = set->scip;
1907 #endif
1908  (*var)->obj = obj;
1909  (*var)->unchangedobj = obj;
1910  (*var)->branchfactor = 1.0;
1911  (*var)->rootsol = 0.0;
1912  (*var)->bestrootsol = 0.0;
1913  (*var)->bestrootredcost = 0.0;
1914  (*var)->bestrootlpobjval = SCIP_INVALID;
1915  (*var)->relaxsol = 0.0;
1916  (*var)->nlpsol = 0.0;
1917  (*var)->primsolavg = 0.5 * (lb + ub);
1918  (*var)->conflictlb = SCIP_REAL_MIN;
1919  (*var)->conflictub = SCIP_REAL_MAX;
1920  (*var)->conflictrelaxedlb = (*var)->conflictlb;
1921  (*var)->conflictrelaxedub = (*var)->conflictub;
1922  (*var)->lazylb = -SCIPsetInfinity(set);
1923  (*var)->lazyub = SCIPsetInfinity(set);
1924  (*var)->glbdom.holelist = NULL;
1925  (*var)->glbdom.lb = lb;
1926  (*var)->glbdom.ub = ub;
1927  (*var)->locdom.holelist = NULL;
1928  (*var)->locdom.lb = lb;
1929  (*var)->locdom.ub = ub;
1930  (*var)->varcopy = varcopy;
1931  (*var)->vardelorig = vardelorig;
1932  (*var)->vartrans = vartrans;
1933  (*var)->vardeltrans = vardeltrans;
1934  (*var)->vardata = vardata;
1935  (*var)->parentvars = NULL;
1936  (*var)->negatedvar = NULL;
1937  (*var)->vlbs = NULL;
1938  (*var)->vubs = NULL;
1939  (*var)->implics = NULL;
1940  (*var)->cliquelist = NULL;
1941  (*var)->eventfilter = NULL;
1942  (*var)->lbchginfos = NULL;
1943  (*var)->ubchginfos = NULL;
1944  (*var)->index = stat->nvaridx;
1945  (*var)->probindex = -1;
1946  (*var)->pseudocandindex = -1;
1947  (*var)->eventqueueindexobj = -1;
1948  (*var)->eventqueueindexlb = -1;
1949  (*var)->eventqueueindexub = -1;
1950  (*var)->parentvarssize = 0;
1951  (*var)->nparentvars = 0;
1952  (*var)->nuses = 0;
1953  (*var)->nlocksdown = 0;
1954  (*var)->nlocksup = 0;
1955  (*var)->branchpriority = 0;
1956  (*var)->branchdirection = SCIP_BRANCHDIR_AUTO; /*lint !e641*/
1957  (*var)->lbchginfossize = 0;
1958  (*var)->nlbchginfos = 0;
1959  (*var)->ubchginfossize = 0;
1960  (*var)->nubchginfos = 0;
1961  (*var)->conflictlbcount = 0;
1962  (*var)->conflictubcount = 0;
1963  (*var)->closestvlbidx = -1;
1964  (*var)->closestvubidx = -1;
1965  (*var)->closestvblpcount = -1;
1966  (*var)->initial = initial;
1967  (*var)->removable = removable;
1968  (*var)->deleted = FALSE;
1969  (*var)->donotmultaggr = FALSE;
1970  (*var)->vartype = vartype; /*lint !e641*/
1971  (*var)->pseudocostflag = FALSE;
1972  (*var)->eventqueueimpl = FALSE;
1973  (*var)->deletable = FALSE;
1974  (*var)->delglobalstructs = FALSE;
1975  (*var)->clqcomponentidx = -1;
1976 
1977  stat->nvaridx++;
1978 
1979  /* create branching and inference history entries */
1980  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1981  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1982 
1983  /* the value based history is only created on demand */
1984  (*var)->valuehistory = NULL;
1985 
1986  return SCIP_OKAY;
1987 }
1988 
1989 /** creates and captures an original problem variable; an integer variable with bounds
1990  * zero and one is automatically converted into a binary variable
1991  */
1993  SCIP_VAR** var, /**< pointer to variable data */
1994  BMS_BLKMEM* blkmem, /**< block memory */
1995  SCIP_SET* set, /**< global SCIP settings */
1996  SCIP_STAT* stat, /**< problem statistics */
1997  const char* name, /**< name of variable, or NULL for automatic name creation */
1998  SCIP_Real lb, /**< lower bound of variable */
1999  SCIP_Real ub, /**< upper bound of variable */
2000  SCIP_Real obj, /**< objective function value */
2001  SCIP_VARTYPE vartype, /**< type of variable */
2002  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2003  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2004  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2005  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2006  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2007  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2008  SCIP_VARDATA* vardata /**< user data for this specific variable */
2009  )
2010 {
2011  assert(var != NULL);
2012  assert(blkmem != NULL);
2013  assert(stat != NULL);
2014 
2015  /* create variable */
2016  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2017  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2018 
2019  /* set variable status and data */
2020  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2021  (*var)->data.original.origdom.holelist = NULL;
2022  (*var)->data.original.origdom.lb = lb;
2023  (*var)->data.original.origdom.ub = ub;
2024  (*var)->data.original.transvar = NULL;
2025 
2026  /* capture variable */
2027  SCIPvarCapture(*var);
2028 
2029  return SCIP_OKAY;
2030 }
2031 
2032 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2033  * zero and one is automatically converted into a binary variable
2034  */
2036  SCIP_VAR** var, /**< pointer to variable data */
2037  BMS_BLKMEM* blkmem, /**< block memory */
2038  SCIP_SET* set, /**< global SCIP settings */
2039  SCIP_STAT* stat, /**< problem statistics */
2040  const char* name, /**< name of variable, or NULL for automatic name creation */
2041  SCIP_Real lb, /**< lower bound of variable */
2042  SCIP_Real ub, /**< upper bound of variable */
2043  SCIP_Real obj, /**< objective function value */
2044  SCIP_VARTYPE vartype, /**< type of variable */
2045  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2046  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2047  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2048  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2049  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2050  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2051  SCIP_VARDATA* vardata /**< user data for this specific variable */
2052  )
2053 {
2054  assert(var != NULL);
2055  assert(blkmem != NULL);
2056 
2057  /* create variable */
2058  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2059  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2060 
2061  /* create event filter for transformed variable */
2062  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2063 
2064  /* set variable status and data */
2065  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2066 
2067  /* capture variable */
2068  SCIPvarCapture(*var);
2069 
2070  return SCIP_OKAY;
2071 }
2072 
2073 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2074  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2075  * copied at all
2076  */
2078  SCIP_VAR** var, /**< pointer to store the target variable */
2079  BMS_BLKMEM* blkmem, /**< block memory */
2080  SCIP_SET* set, /**< global SCIP settings */
2081  SCIP_STAT* stat, /**< problem statistics */
2082  SCIP* sourcescip, /**< source SCIP data structure */
2083  SCIP_VAR* sourcevar, /**< source variable */
2084  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2085  * target variables */
2086  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2087  * target constraints */
2088  SCIP_Bool global /**< should global or local bounds be used? */
2089  )
2090 {
2091  SCIP_VARDATA* targetdata;
2092  SCIP_RESULT result;
2093  SCIP_Real lb;
2094  SCIP_Real ub;
2095 
2096  assert(set != NULL);
2097  assert(blkmem != NULL);
2098  assert(stat != NULL);
2099  assert(sourcescip != NULL);
2100  assert(sourcevar != NULL);
2101  assert(var != NULL);
2102  assert(set->stage == SCIP_STAGE_PROBLEM);
2103  assert(varmap != NULL);
2104  assert(consmap != NULL);
2105 
2106  /** @todo copy hole lists */
2107  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2108  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2109 
2110  result = SCIP_DIDNOTRUN;
2111  targetdata = NULL;
2112 
2113  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2114  {
2115  lb = SCIPvarGetLbOriginal(sourcevar);
2116  ub = SCIPvarGetUbOriginal(sourcevar);
2117  }
2118  else
2119  {
2120  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2121  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2122  }
2123 
2124  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2125  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2126  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2127  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2128  NULL, NULL, NULL, NULL, NULL) );
2129  assert(*var != NULL);
2130 
2131  /* directly copy donotmultaggr flag */
2132  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2133 
2134  /* insert variable into mapping between source SCIP and the target SCIP */
2135  assert(!SCIPhashmapExists(varmap, sourcevar));
2136  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2137 
2138  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2139  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2140  {
2141  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2142  varmap, consmap, (*var), &targetdata, &result) );
2143 
2144  /* evaluate result */
2145  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2146  {
2147  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2148  return SCIP_INVALIDRESULT;
2149  }
2150 
2151  assert(targetdata == NULL || result == SCIP_SUCCESS);
2152 
2153  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2154  if( result == SCIP_SUCCESS )
2155  {
2156  (*var)->varcopy = sourcevar->varcopy;
2157  (*var)->vardelorig = sourcevar->vardelorig;
2158  (*var)->vartrans = sourcevar->vartrans;
2159  (*var)->vardeltrans = sourcevar->vardeltrans;
2160  (*var)->vardata = targetdata;
2161  }
2162  }
2163 
2164  /* we initialize histories of the variables by copying the source variable-information */
2165  if( set->history_allowtransfer )
2166  {
2167  SCIPvarMergeHistories((*var), sourcevar, stat);
2168  }
2169 
2170  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2171  * methods
2172  */
2173  if( result == SCIP_SUCCESS )
2174  {
2175  (*var)->varcopy = sourcevar->varcopy;
2176  (*var)->vardelorig = sourcevar->vardelorig;
2177  (*var)->vartrans = sourcevar->vartrans;
2178  (*var)->vardeltrans = sourcevar->vardeltrans;
2179  (*var)->vardata = targetdata;
2180  }
2181 
2182  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2183 
2184  return SCIP_OKAY;
2185 }
2186 
2187 /** parse given string for a SCIP_Real bound */
2188 static
2190  SCIP_SET* set, /**< global SCIP settings */
2191  const char* str, /**< string to parse */
2192  SCIP_Real* value, /**< pointer to store the parsed value */
2193  char** endptr /**< pointer to store the final string position if successfully parsed */
2194  )
2195 {
2196  /* first check for infinity value */
2197  if( strncmp(str, "+inf", 4) == 0 )
2198  {
2199  *value = SCIPsetInfinity(set);
2200  (*endptr) = (char*)str + 4;
2201  }
2202  else if( strncmp(str, "-inf", 4) == 0 )
2203  {
2204  *value = -SCIPsetInfinity(set);
2205  (*endptr) = (char*)str + 4;
2206  }
2207  else
2208  {
2209  if( !SCIPstrToRealValue(str, value, endptr) )
2210  return SCIP_READERROR;
2211  }
2212 
2213  return SCIP_OKAY;
2214 }
2215 
2216 /** parse the characters as bounds */
2217 static
2219  SCIP_SET* set, /**< global SCIP settings */
2220  const char* str, /**< string to parse */
2221  char* type, /**< bound type (global, local, or lazy) */
2222  SCIP_Real* lb, /**< pointer to store the lower bound */
2223  SCIP_Real* ub, /**< pointer to store the upper bound */
2224  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2225  )
2226 {
2227  char token[SCIP_MAXSTRLEN];
2228 
2229  SCIPsetDebugMsg(set, "parsing bounds: '%s'\n", str);
2230 
2231  /* get bound type */
2232  SCIPstrCopySection(str, ' ', ' ', type, SCIP_MAXSTRLEN, endptr);
2233  if ( strncmp(type, "original", 8) != 0 && strncmp(type, "global", 6) != 0 && strncmp(type, "local", 5) != 0 && strncmp(type, "lazy", 4) != 0 )
2234  {
2235  SCIPsetDebugMsg(set, "unkown bound type <%s>\n", type);
2236  *endptr = NULL;
2237  return SCIP_OKAY;
2238  }
2239 
2240  SCIPsetDebugMsg(set, "parsed bound type <%s>\n", type);
2241 
2242  /* get lower bound */
2243  SCIPstrCopySection(str, '[', ',', token, SCIP_MAXSTRLEN, endptr);
2244  str = *endptr;
2245  SCIP_CALL( parseValue(set, token, lb, endptr) );
2246 
2247  /* get upper bound */
2248  SCIP_CALL( parseValue(set, str, ub, endptr) );
2249 
2250  SCIPsetDebugMsg(set, "parsed bounds: [%g,%g]\n", *lb, *ub);
2251 
2252  /* skip end of bounds */
2253  while ( **endptr != '\0' && (**endptr == ']' || **endptr == ',') )
2254  ++(*endptr);
2255 
2256  return SCIP_OKAY;
2257 }
2258 
2259 /** parses a given string for a variable informations */
2260 static
2262  SCIP_SET* set, /**< global SCIP settings */
2263  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2264  const char* str, /**< string to parse */
2265  char* name, /**< pointer to store the variable name */
2266  SCIP_Real* lb, /**< pointer to store the lower bound */
2267  SCIP_Real* ub, /**< pointer to store the upper bound */
2268  SCIP_Real* obj, /**< pointer to store the objective coefficient */
2269  SCIP_VARTYPE* vartype, /**< pointer to store the variable type */
2270  SCIP_Real* lazylb, /**< pointer to store if the lower bound is lazy */
2271  SCIP_Real* lazyub, /**< pointer to store if the upper bound is lazy */
2272  SCIP_Bool local, /**< should the local bound be applied */
2273  char** endptr, /**< pointer to store the final string position if successfully */
2274  SCIP_Bool* success /**< pointer store if the paring process was successful */
2275  )
2276 {
2277  SCIP_Real parsedlb;
2278  SCIP_Real parsedub;
2279  char token[SCIP_MAXSTRLEN];
2280  char* strptr;
2281  int i;
2282 
2283  assert(lb != NULL);
2284  assert(ub != NULL);
2285  assert(obj != NULL);
2286  assert(vartype != NULL);
2287  assert(lazylb != NULL);
2288  assert(lazyub != NULL);
2289  assert(success != NULL);
2290 
2291  (*success) = TRUE;
2292 
2293  /* copy variable type */
2294  SCIPstrCopySection(str, '[', ']', token, SCIP_MAXSTRLEN, endptr);
2295  assert(str != *endptr);
2296  SCIPsetDebugMsg(set, "parsed variable type <%s>\n", token);
2297 
2298  /* get variable type */
2299  if( strncmp(token, "binary", 3) == 0 )
2300  (*vartype) = SCIP_VARTYPE_BINARY;
2301  else if( strncmp(token, "integer", 3) == 0 )
2302  (*vartype) = SCIP_VARTYPE_INTEGER;
2303  else if( strncmp(token, "implicit", 3) == 0 )
2304  (*vartype) = SCIP_VARTYPE_IMPLINT;
2305  else if( strncmp(token, "continuous", 3) == 0 )
2306  (*vartype) = SCIP_VARTYPE_CONTINUOUS;
2307  else
2308  {
2309  SCIPmessagePrintWarning(messagehdlr, "unknown variable type\n");
2310  (*success) = FALSE;
2311  return SCIP_OKAY;
2312  }
2313 
2314  /* move string pointer behind variable type */
2315  str = *endptr;
2316 
2317  /* get variable name */
2318  SCIPstrCopySection(str, '<', '>', name, SCIP_MAXSTRLEN, endptr);
2319  assert(endptr != NULL);
2320  SCIPsetDebugMsg(set, "parsed variable name <%s>\n", name);
2321 
2322  /* move string pointer behind variable name */
2323  str = *endptr;
2324 
2325  /* cut out objective coefficient */
2326  SCIPstrCopySection(str, '=', ',', token, SCIP_MAXSTRLEN, endptr);
2327 
2328  /* move string pointer behind objective coefficient */
2329  str = *endptr;
2330 
2331  /* get objective coefficient */
2332  if( !SCIPstrToRealValue(token, obj, endptr) )
2333  {
2334  *endptr = NULL;
2335  return SCIP_READERROR;
2336  }
2337 
2338  SCIPsetDebugMsg(set, "parsed objective coefficient <%g>\n", *obj);
2339 
2340  /* parse global/original bounds */
2341  SCIP_CALL( parseBounds(set, str, token, lb, ub, endptr) );
2342  assert(strncmp(token, "global", 6) == 0 || strncmp(token, "original", 8) == 0);
2343 
2344  /* initialize the lazy bound */
2345  *lazylb = -SCIPsetInfinity(set);
2346  *lazyub = SCIPsetInfinity(set);
2347 
2348  /* store pointer */
2349  strptr = *endptr;
2350 
2351  /* possibly parse optional local and lazy bounds */
2352  for( i = 0; i < 2 && *endptr != NULL && **endptr != '\0'; ++i )
2353  {
2354  /* start after previous bounds */
2355  strptr = *endptr;
2356 
2357  /* parse global bounds */
2358  SCIP_CALL( parseBounds(set, strptr, token, &parsedlb, &parsedub, endptr) );
2359 
2360  /* stop if parsing of bounds failed */
2361  if( *endptr == NULL )
2362  break;
2363 
2364  if( strncmp(token, "local", 5) == 0 && local )
2365  {
2366  *lb = parsedlb;
2367  *ub = parsedub;
2368  }
2369  else if( strncmp(token, "lazy", 4) == 0 )
2370  {
2371  *lazylb = parsedlb;
2372  *lazyub = parsedub;
2373  }
2374  }
2375 
2376  /* restore pointer */
2377  if ( *endptr == NULL )
2378  *endptr = strptr;
2379 
2380  /* check bounds for binary variables */
2381  if ( (*vartype) == SCIP_VARTYPE_BINARY )
2382  {
2383  if ( SCIPsetIsLT(set, *lb, 0.0) || SCIPsetIsGT(set, *ub, 1.0) )
2384  {
2385  SCIPerrorMessage("Parsed invalid bounds for binary variable <%s>: [%f, %f].\n", name, *lb, *ub);
2386  return SCIP_READERROR;
2387  }
2388  if ( !SCIPsetIsInfinity(set, -(*lazylb)) && !SCIPsetIsInfinity(set, *lazyub) &&
2389  ( SCIPsetIsLT(set, *lazylb, 0.0) || SCIPsetIsGT(set, *lazyub, 1.0) ) )
2390  {
2391  SCIPerrorMessage("Parsed invalid lazy bounds for binary variable <%s>: [%f, %f].\n", name, *lazylb, *lazyub);
2392  return SCIP_READERROR;
2393  }
2394  }
2395 
2396  return SCIP_OKAY;
2397 }
2398 
2399 /** parses variable information (in cip format) out of a string; if the parsing process was successful an original
2400  * variable is created and captured; if variable is of integral type, fractional bounds are automatically rounded; an
2401  * integer variable with bounds zero and one is automatically converted into a binary variable
2402  */
2404  SCIP_VAR** var, /**< pointer to variable data */
2405  BMS_BLKMEM* blkmem, /**< block memory */
2406  SCIP_SET* set, /**< global SCIP settings */
2407  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2408  SCIP_STAT* stat, /**< problem statistics */
2409  const char* str, /**< string to parse */
2410  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2411  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2412  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2413  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2414  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2415  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2416  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2417  char** endptr, /**< pointer to store the final string position if successfully */
2418  SCIP_Bool* success /**< pointer store if the paring process was successful */
2419  )
2420 {
2421  char name[SCIP_MAXSTRLEN];
2422  SCIP_Real lb;
2423  SCIP_Real ub;
2424  SCIP_Real obj;
2425  SCIP_VARTYPE vartype;
2426  SCIP_Real lazylb;
2427  SCIP_Real lazyub;
2428 
2429  assert(var != NULL);
2430  assert(blkmem != NULL);
2431  assert(stat != NULL);
2432  assert(endptr != NULL);
2433  assert(success != NULL);
2434 
2435  /* parse string in cip format for variable information */
2436  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, FALSE, endptr, success) );
2437 
2438  if( *success )
2439  {
2440  /* create variable */
2441  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2442  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2443 
2444  /* set variable status and data */
2445  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2446  (*var)->data.original.origdom.holelist = NULL;
2447  (*var)->data.original.origdom.lb = lb;
2448  (*var)->data.original.origdom.ub = ub;
2449  (*var)->data.original.transvar = NULL;
2450 
2451  /* set lazy status of variable bounds */
2452  (*var)->lazylb = lazylb;
2453  (*var)->lazyub = lazyub;
2454 
2455  /* capture variable */
2456  SCIPvarCapture(*var);
2457  }
2458 
2459  return SCIP_OKAY;
2460 }
2461 
2462 /** parses variable information (in cip format) out of a string; if the parsing process was successful a loose variable
2463  * belonging to the transformed problem is created and captured; if variable is of integral type, fractional bounds are
2464  * automatically rounded; an integer variable with bounds zero and one is automatically converted into a binary
2465  * variable
2466  */
2468  SCIP_VAR** var, /**< pointer to variable data */
2469  BMS_BLKMEM* blkmem, /**< block memory */
2470  SCIP_SET* set, /**< global SCIP settings */
2471  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2472  SCIP_STAT* stat, /**< problem statistics */
2473  const char* str, /**< string to parse */
2474  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2475  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2476  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2477  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable */
2478  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data */
2479  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable */
2480  SCIP_VARDATA* vardata, /**< user data for this specific variable */
2481  char** endptr, /**< pointer to store the final string position if successfully */
2482  SCIP_Bool* success /**< pointer store if the paring process was successful */
2483  )
2484 {
2485  char name[SCIP_MAXSTRLEN];
2486  SCIP_Real lb;
2487  SCIP_Real ub;
2488  SCIP_Real obj;
2489  SCIP_VARTYPE vartype;
2490  SCIP_Real lazylb;
2491  SCIP_Real lazyub;
2492 
2493  assert(var != NULL);
2494  assert(blkmem != NULL);
2495  assert(endptr != NULL);
2496  assert(success != NULL);
2497 
2498  /* parse string in cip format for variable information */
2499  SCIP_CALL( varParse(set, messagehdlr, str, name, &lb, &ub, &obj, &vartype, &lazylb, &lazyub, TRUE, endptr, success) );
2500 
2501  if( *success )
2502  {
2503  /* create variable */
2504  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2505  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2506 
2507  /* create event filter for transformed variable */
2508  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2509 
2510  /* set variable status and data */
2511  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2512 
2513  /* set lazy status of variable bounds */
2514  (*var)->lazylb = lazylb;
2515  (*var)->lazyub = lazyub;
2516 
2517  /* capture variable */
2518  SCIPvarCapture(*var);
2519  }
2520 
2521  return SCIP_OKAY;
2522 }
2523 
2524 /** ensures, that parentvars array of var can store at least num entries */
2525 static
2527  SCIP_VAR* var, /**< problem variable */
2528  BMS_BLKMEM* blkmem, /**< block memory */
2529  SCIP_SET* set, /**< global SCIP settings */
2530  int num /**< minimum number of entries to store */
2531  )
2532 {
2533  assert(var->nparentvars <= var->parentvarssize);
2534 
2535  if( num > var->parentvarssize )
2536  {
2537  int newsize;
2538 
2539  newsize = SCIPsetCalcMemGrowSize(set, num);
2540  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &var->parentvars, var->parentvarssize, newsize) );
2541  var->parentvarssize = newsize;
2542  }
2543  assert(num <= var->parentvarssize);
2544 
2545  return SCIP_OKAY;
2546 }
2547 
2548 /** adds variable to parent list of a variable and captures parent variable */
2549 static
2551  SCIP_VAR* var, /**< variable to add parent to */
2552  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
2553  SCIP_SET* set, /**< global SCIP settings */
2554  SCIP_VAR* parentvar /**< parent variable to add */
2555  )
2556 {
2557  assert(var != NULL);
2558  assert(parentvar != NULL);
2559 
2560  /* the direct original counterpart must be stored as first parent */
2561  assert(var->nparentvars == 0 || SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL);
2562 
2563  SCIPsetDebugMsg(set, "adding parent <%s>[%p] to variable <%s>[%p] in slot %d\n",
2564  parentvar->name, (void*)parentvar, var->name, (void*)var, var->nparentvars);
2565 
2566  SCIP_CALL( varEnsureParentvarsSize(var, blkmem, set, var->nparentvars+1) );
2567 
2568  var->parentvars[var->nparentvars] = parentvar;
2569  var->nparentvars++;
2570 
2571  SCIPvarCapture(parentvar);
2572 
2573  return SCIP_OKAY;
2574 }
2575 
2576 /** deletes and releases all variables from the parent list of a variable, frees the memory of parents array */
2577 static
2579  SCIP_VAR** var, /**< pointer to variable */
2580  BMS_BLKMEM* blkmem, /**< block memory */
2581  SCIP_SET* set, /**< global SCIP settings */
2582  SCIP_EVENTQUEUE* eventqueue, /**< event queue (or NULL, if it's an original variable) */
2583  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2584  )
2585 {
2586  SCIP_VAR* parentvar;
2587  int i;
2588 
2589  SCIPsetDebugMsg(set, "free parents of <%s>\n", (*var)->name);
2590 
2591  /* release the parent variables and remove the link from the parent variable to the child */
2592  for( i = 0; i < (*var)->nparentvars; ++i )
2593  {
2594  assert((*var)->parentvars != NULL);
2595  parentvar = (*var)->parentvars[i];
2596  assert(parentvar != NULL);
2597 
2598  switch( SCIPvarGetStatus(parentvar) )
2599  {
2601  assert(parentvar->data.original.transvar == *var);
2602  assert(&parentvar->data.original.transvar != var);
2603  parentvar->data.original.transvar = NULL;
2604  break;
2605 
2607  assert(parentvar->data.aggregate.var == *var);
2608  assert(&parentvar->data.aggregate.var != var);
2609  parentvar->data.aggregate.var = NULL;
2610  break;
2611 
2612 #if 0
2613  /* The following code is unclear: should the current variable be removed from its parents? */
2615  assert(parentvar->data.multaggr.vars != NULL);
2616  for( v = 0; v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] != *var; ++v )
2617  {}
2618  assert(v < parentvar->data.multaggr.nvars && parentvar->data.multaggr.vars[v] == *var);
2619  if( v < parentvar->data.multaggr.nvars-1 )
2620  {
2621  parentvar->data.multaggr.vars[v] = parentvar->data.multaggr.vars[parentvar->data.multaggr.nvars-1];
2622  parentvar->data.multaggr.scalars[v] = parentvar->data.multaggr.scalars[parentvar->data.multaggr.nvars-1];
2623  }
2624  parentvar->data.multaggr.nvars--;
2625  break;
2626 #endif
2627 
2629  assert(parentvar->negatedvar == *var);
2630  assert((*var)->negatedvar == parentvar);
2631  parentvar->negatedvar = NULL;
2632  (*var)->negatedvar = NULL;
2633  break;
2634 
2635  default:
2636  SCIPerrorMessage("parent variable is neither ORIGINAL, AGGREGATED nor NEGATED\n");
2637  return SCIP_INVALIDDATA;
2638  } /*lint !e788*/
2639 
2640  SCIP_CALL( SCIPvarRelease(&(*var)->parentvars[i], blkmem, set, eventqueue, lp) );
2641  }
2642 
2643  /* free parentvars array */
2644  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->parentvars, (*var)->parentvarssize);
2645 
2646  return SCIP_OKAY;
2647 }
2648 
2649 /** frees a variable */
2650 static
2652  SCIP_VAR** var, /**< pointer to variable */
2653  BMS_BLKMEM* blkmem, /**< block memory */
2654  SCIP_SET* set, /**< global SCIP settings */
2655  SCIP_EVENTQUEUE* eventqueue, /**< event queue (may be NULL, if it's not a column variable) */
2656  SCIP_LP* lp /**< current LP data (may be NULL, if it's not a column variable) */
2657  )
2658 {
2659  assert(var != NULL);
2660  assert(*var != NULL);
2661  assert(SCIPvarGetStatus(*var) != SCIP_VARSTATUS_COLUMN || &(*var)->data.col->var != var);
2662  assert((*var)->nuses == 0);
2663  assert((*var)->probindex == -1);
2664 
2665  SCIPsetDebugMsg(set, "free variable <%s> with status=%d\n", (*var)->name, SCIPvarGetStatus(*var));
2666 
2667  switch( SCIPvarGetStatus(*var) )
2668  {
2670  assert((*var)->data.original.transvar == NULL); /* cannot free variable, if transformed variable is still existing */
2671  holelistFree(&(*var)->data.original.origdom.holelist, blkmem);
2672  assert((*var)->data.original.origdom.holelist == NULL);
2673  break;
2674  case SCIP_VARSTATUS_LOOSE:
2675  break;
2676  case SCIP_VARSTATUS_COLUMN:
2677  SCIP_CALL( SCIPcolFree(&(*var)->data.col, blkmem, set, eventqueue, lp) ); /* free corresponding LP column */
2678  break;
2679  case SCIP_VARSTATUS_FIXED:
2681  break;
2683  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.vars, (*var)->data.multaggr.varssize);
2684  BMSfreeBlockMemoryArray(blkmem, &(*var)->data.multaggr.scalars, (*var)->data.multaggr.varssize);
2685  break;
2687  break;
2688  default:
2689  SCIPerrorMessage("unknown variable status\n");
2690  return SCIP_INVALIDDATA;
2691  }
2692 
2693  /* release all parent variables and free the parentvars array */
2694  SCIP_CALL( varFreeParents(var, blkmem, set, eventqueue, lp) );
2695 
2696  /* free user data */
2698  {
2699  if( (*var)->vardelorig != NULL )
2700  {
2701  SCIP_CALL( (*var)->vardelorig(set->scip, *var, &(*var)->vardata) );
2702  }
2703  }
2704  else
2705  {
2706  if( (*var)->vardeltrans != NULL )
2707  {
2708  SCIP_CALL( (*var)->vardeltrans(set->scip, *var, &(*var)->vardata) );
2709  }
2710  }
2711 
2712  /* free event filter */
2713  if( (*var)->eventfilter != NULL )
2714  {
2715  SCIP_CALL( SCIPeventfilterFree(&(*var)->eventfilter, blkmem, set) );
2716  }
2717  assert((*var)->eventfilter == NULL);
2718 
2719  /* free hole lists */
2720  holelistFree(&(*var)->glbdom.holelist, blkmem);
2721  holelistFree(&(*var)->locdom.holelist, blkmem);
2722  assert((*var)->glbdom.holelist == NULL);
2723  assert((*var)->locdom.holelist == NULL);
2724 
2725  /* free variable bounds data structures */
2726  SCIPvboundsFree(&(*var)->vlbs, blkmem);
2727  SCIPvboundsFree(&(*var)->vubs, blkmem);
2728 
2729  /* free implications data structures */
2730  SCIPimplicsFree(&(*var)->implics, blkmem);
2731 
2732  /* free clique list data structures */
2733  SCIPcliquelistFree(&(*var)->cliquelist, blkmem);
2734 
2735  /* free bound change information arrays */
2736  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->lbchginfos, (*var)->lbchginfossize);
2737  BMSfreeBlockMemoryArrayNull(blkmem, &(*var)->ubchginfos, (*var)->ubchginfossize);
2738 
2739  /* free branching and inference history entries */
2740  SCIPhistoryFree(&(*var)->history, blkmem);
2741  SCIPhistoryFree(&(*var)->historycrun, blkmem);
2742  SCIPvaluehistoryFree(&(*var)->valuehistory, blkmem);
2743 
2744  /* free variable data structure */
2745  BMSfreeBlockMemoryArray(blkmem, &(*var)->name, strlen((*var)->name)+1);
2746  BMSfreeBlockMemory(blkmem, var);
2747 
2748  return SCIP_OKAY;
2749 }
2750 
2751 /** increases usage counter of variable */
2752 void SCIPvarCapture(
2753  SCIP_VAR* var /**< variable */
2754  )
2755 {
2756  assert(var != NULL);
2757  assert(var->nuses >= 0);
2758 
2759  SCIPdebugMessage("capture variable <%s> with nuses=%d\n", var->name, var->nuses);
2760  var->nuses++;
2761 }
2762 
2763 /** decreases usage counter of variable, and frees memory if necessary */
2765  SCIP_VAR** var, /**< pointer to variable */
2766  BMS_BLKMEM* blkmem, /**< block memory */
2767  SCIP_SET* set, /**< global SCIP settings */
2768  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
2769  SCIP_LP* lp /**< current LP data (or NULL, if it's an original variable) */
2770  )
2771 {
2772  assert(var != NULL);
2773  assert(*var != NULL);
2774  assert((*var)->nuses >= 1);
2775  assert(blkmem != NULL);
2776  assert((*var)->scip == set->scip);
2777 
2778  SCIPsetDebugMsg(set, "release variable <%s> with nuses=%d\n", (*var)->name, (*var)->nuses);
2779  (*var)->nuses--;
2780  if( (*var)->nuses == 0 )
2781  {
2782  SCIP_CALL( varFree(var, blkmem, set, eventqueue, lp) );
2783  }
2784 
2785  *var = NULL;
2786 
2787  return SCIP_OKAY;
2788 }
2789 
2790 /** change variable name */
2792  SCIP_VAR* var, /**< problem variable */
2793  BMS_BLKMEM* blkmem, /**< block memory */
2794  const char* name /**< name of variable */
2795  )
2796 {
2797  assert(name != NULL);
2798 
2799  /* remove old variable name */
2800  BMSfreeBlockMemoryArray(blkmem, &var->name, strlen(var->name)+1);
2801 
2802  /* set new variable name */
2803  SCIP_CALL( varSetName(var, blkmem, NULL, name) );
2804 
2805  return SCIP_OKAY;
2806 }
2807 
2808 /** initializes variable data structure for solving */
2809 void SCIPvarInitSolve(
2810  SCIP_VAR* var /**< problem variable */
2811  )
2812 {
2813  assert(var != NULL);
2814 
2816  var->conflictlbcount = 0;
2817  var->conflictubcount = 0;
2818 }
2819 
2820 /** outputs the given bounds into the file stream */
2821 static
2822 void printBounds(
2823  SCIP_SET* set, /**< global SCIP settings */
2824  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2825  FILE* file, /**< output file (or NULL for standard output) */
2826  SCIP_Real lb, /**< lower bound */
2827  SCIP_Real ub, /**< upper bound */
2828  const char* name /**< bound type name */
2829  )
2830 {
2831  assert(set != NULL);
2832 
2833  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=", name);
2834  if( SCIPsetIsInfinity(set, lb) )
2835  SCIPmessageFPrintInfo(messagehdlr, file, "[+inf,");
2836  else if( SCIPsetIsInfinity(set, -lb) )
2837  SCIPmessageFPrintInfo(messagehdlr, file, "[-inf,");
2838  else
2839  SCIPmessageFPrintInfo(messagehdlr, file, "[%.15g,", lb);
2840  if( SCIPsetIsInfinity(set, ub) )
2841  SCIPmessageFPrintInfo(messagehdlr, file, "+inf]");
2842  else if( SCIPsetIsInfinity(set, -ub) )
2843  SCIPmessageFPrintInfo(messagehdlr, file, "-inf]");
2844  else
2845  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g]", ub);
2846 }
2847 
2848 /** prints hole list to file stream */
2849 static
2850 void printHolelist(
2851  SCIP_SET* set, /**< global SCIP settings */
2852  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2853  FILE* file, /**< output file (or NULL for standard output) */
2854  SCIP_HOLELIST* holelist, /**< hole list pointer to hole of interest */
2855  const char* name /**< hole type name */
2856  )
2857 { /*lint --e{715}*/
2858  SCIP_Real left;
2859  SCIP_Real right;
2860 
2861  if( holelist == NULL )
2862  return;
2863 
2864  left = SCIPholelistGetLeft(holelist);
2865  right = SCIPholelistGetRight(holelist);
2866 
2867  /* display first hole */
2868  SCIPmessageFPrintInfo(messagehdlr, file, ", %s=(%g,%g)", name, left, right);
2869  holelist = SCIPholelistGetNext(holelist);
2870 
2871  while(holelist != NULL )
2872  {
2873  left = SCIPholelistGetLeft(holelist);
2874  right = SCIPholelistGetRight(holelist);
2875 
2876  /* display hole */
2877  SCIPmessageFPrintInfo(messagehdlr, file, "(%g,%g)", left, right);
2878 
2879  /* get next hole */
2880  holelist = SCIPholelistGetNext(holelist);
2881  }
2882 }
2883 
2884 /** outputs variable information into file stream */
2886  SCIP_VAR* var, /**< problem variable */
2887  SCIP_SET* set, /**< global SCIP settings */
2888  SCIP_MESSAGEHDLR* messagehdlr, /**< message handler */
2889  FILE* file /**< output file (or NULL for standard output) */
2890  )
2891 {
2892  SCIP_HOLELIST* holelist;
2893  SCIP_Real lb;
2894  SCIP_Real ub;
2895  int i;
2896 
2897  assert(var != NULL);
2898  assert(var->scip == set->scip);
2899 
2900  /* type of variable */
2901  switch( SCIPvarGetType(var) )
2902  {
2903  case SCIP_VARTYPE_BINARY:
2904  SCIPmessageFPrintInfo(messagehdlr, file, " [binary]");
2905  break;
2906  case SCIP_VARTYPE_INTEGER:
2907  SCIPmessageFPrintInfo(messagehdlr, file, " [integer]");
2908  break;
2909  case SCIP_VARTYPE_IMPLINT:
2910  SCIPmessageFPrintInfo(messagehdlr, file, " [implicit]");
2911  break;
2913  SCIPmessageFPrintInfo(messagehdlr, file, " [continuous]");
2914  break;
2915  default:
2916  SCIPerrorMessage("unknown variable type\n");
2917  SCIPABORT();
2918  return SCIP_ERROR; /*lint !e527*/
2919  }
2920 
2921  /* name */
2922  SCIPmessageFPrintInfo(messagehdlr, file, " <%s>:", var->name);
2923 
2924  /* objective value */
2925  SCIPmessageFPrintInfo(messagehdlr, file, " obj=%.15g", var->obj);
2926 
2927  /* bounds (global bounds for transformed variables, original bounds for original variables) */
2928  if( !SCIPvarIsTransformed(var) )
2929  {
2930  /* output original bound */
2931  lb = SCIPvarGetLbOriginal(var);
2932  ub = SCIPvarGetUbOriginal(var);
2933  printBounds(set, messagehdlr, file, lb, ub, "original bounds");
2934 
2935  /* output lazy bound */
2936  lb = SCIPvarGetLbLazy(var);
2937  ub = SCIPvarGetUbLazy(var);
2938 
2939  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2940  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2941  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2942 
2943  holelist = SCIPvarGetHolelistOriginal(var);
2944  printHolelist(set, messagehdlr, file, holelist, "original holes");
2945  }
2946  else
2947  {
2948  /* output global bound */
2949  lb = SCIPvarGetLbGlobal(var);
2950  ub = SCIPvarGetUbGlobal(var);
2951  printBounds(set, messagehdlr, file, lb, ub, "global bounds");
2952 
2953  /* output local bound */
2954  lb = SCIPvarGetLbLocal(var);
2955  ub = SCIPvarGetUbLocal(var);
2956  printBounds(set, messagehdlr, file, lb, ub, "local bounds");
2957 
2958  /* output lazy bound */
2959  lb = SCIPvarGetLbLazy(var);
2960  ub = SCIPvarGetUbLazy(var);
2961 
2962  /* only display the lazy bounds if they are different from [-infinity,infinity] */
2963  if( !SCIPsetIsInfinity(set, -lb) || !SCIPsetIsInfinity(set, ub) )
2964  printBounds(set, messagehdlr, file, lb, ub, "lazy bounds");
2965 
2966  /* global hole list */
2967  holelist = SCIPvarGetHolelistGlobal(var);
2968  printHolelist(set, messagehdlr, file, holelist, "global holes");
2969 
2970  /* local hole list */
2971  holelist = SCIPvarGetHolelistLocal(var);
2972  printHolelist(set, messagehdlr, file, holelist, "local holes");
2973  }
2974 
2975  /* fixings and aggregations */
2976  switch( SCIPvarGetStatus(var) )
2977  {
2979  case SCIP_VARSTATUS_LOOSE:
2980  case SCIP_VARSTATUS_COLUMN:
2981  break;
2982 
2983  case SCIP_VARSTATUS_FIXED:
2984  SCIPmessageFPrintInfo(messagehdlr, file, ", fixed:");
2985  if( SCIPsetIsInfinity(set, var->glbdom.lb) )
2986  SCIPmessageFPrintInfo(messagehdlr, file, "+inf");
2987  else if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
2988  SCIPmessageFPrintInfo(messagehdlr, file, "-inf");
2989  else
2990  SCIPmessageFPrintInfo(messagehdlr, file, "%.15g", var->glbdom.lb);
2991  break;
2992 
2994  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
2995  if( !SCIPsetIsZero(set, var->data.aggregate.constant) )
2996  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.aggregate.constant);
2997  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.aggregate.scalar, SCIPvarGetName(var->data.aggregate.var));
2998  break;
2999 
3001  SCIPmessageFPrintInfo(messagehdlr, file, ", aggregated:");
3002  if( var->data.multaggr.nvars == 0 || !SCIPsetIsZero(set, var->data.multaggr.constant) )
3003  SCIPmessageFPrintInfo(messagehdlr, file, " %.15g", var->data.multaggr.constant);
3004  for( i = 0; i < var->data.multaggr.nvars; ++i )
3005  SCIPmessageFPrintInfo(messagehdlr, file, " %+.15g<%s>", var->data.multaggr.scalars[i], SCIPvarGetName(var->data.multaggr.vars[i]));
3006  break;
3007 
3009  SCIPmessageFPrintInfo(messagehdlr, file, ", negated: %.15g - <%s>", var->data.negate.constant, SCIPvarGetName(var->negatedvar));
3010  break;
3011 
3012  default:
3013  SCIPerrorMessage("unknown variable status\n");
3014  SCIPABORT();
3015  return SCIP_ERROR; /*lint !e527*/
3016  }
3017 
3018  SCIPmessageFPrintInfo(messagehdlr, file, "\n");
3019 
3020  return SCIP_OKAY;
3021 }
3022 
3023 /** issues a VARUNLOCKED event on the given variable */
3024 static
3026  SCIP_VAR* var, /**< problem variable to change */
3027  BMS_BLKMEM* blkmem, /**< block memory */
3028  SCIP_SET* set, /**< global SCIP settings */
3029  SCIP_EVENTQUEUE* eventqueue /**< event queue */
3030  )
3031 {
3032  SCIP_EVENT* event;
3033 
3034  assert(var != NULL);
3035  assert(var->nlocksdown <= 1 && var->nlocksup <= 1);
3036  assert(var->scip == set->scip);
3037 
3038  /* issue VARUNLOCKED event on variable */
3039  SCIP_CALL( SCIPeventCreateVarUnlocked(&event, blkmem, var) );
3040  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3041 
3042  return SCIP_OKAY;
3043 }
3044 
3045 /** modifies lock numbers for rounding */
3047  SCIP_VAR* var, /**< problem variable */
3048  BMS_BLKMEM* blkmem, /**< block memory */
3049  SCIP_SET* set, /**< global SCIP settings */
3050  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3051  int addnlocksdown, /**< increase in number of rounding down locks */
3052  int addnlocksup /**< increase in number of rounding up locks */
3053  )
3054 {
3055  SCIP_VAR* lockvar;
3056 
3057  assert(var != NULL);
3058  assert(var->nlocksup >= 0);
3059  assert(var->nlocksdown >= 0);
3060  assert(var->scip == set->scip);
3061 
3062  if( addnlocksdown == 0 && addnlocksup == 0 )
3063  return SCIP_OKAY;
3064 
3065  SCIPsetDebugMsg(set, "add rounding locks %d/%d to variable <%s> (locks=%d/%d)\n",
3066  addnlocksdown, addnlocksup, var->name, var->nlocksdown, var->nlocksup);
3067 
3068  lockvar = var;
3069 
3070  while( TRUE ) /*lint !e716 */
3071  {
3072  assert(lockvar != NULL);
3073 
3074  switch( SCIPvarGetStatus(lockvar) )
3075  {
3077  if( lockvar->data.original.transvar != NULL )
3078  {
3079  lockvar = lockvar->data.original.transvar;
3080  break;
3081  }
3082  else
3083  {
3084  lockvar->nlocksdown += addnlocksdown;
3085  lockvar->nlocksup += addnlocksup;
3086 
3087  assert(lockvar->nlocksdown >= 0);
3088  assert(lockvar->nlocksup >= 0);
3089 
3090  return SCIP_OKAY;
3091  }
3092  case SCIP_VARSTATUS_LOOSE:
3093  case SCIP_VARSTATUS_COLUMN:
3094  case SCIP_VARSTATUS_FIXED:
3095  lockvar->nlocksdown += addnlocksdown;
3096  lockvar->nlocksup += addnlocksup;
3097 
3098  assert(lockvar->nlocksdown >= 0);
3099  assert(lockvar->nlocksup >= 0);
3100 
3101  if( lockvar->nlocksdown <= 1 && lockvar->nlocksup <= 1 )
3102  {
3103  SCIP_CALL( varEventVarUnlocked(lockvar, blkmem, set, eventqueue) );
3104  }
3105 
3106  return SCIP_OKAY;
3108  if( lockvar->data.aggregate.scalar < 0.0 )
3109  {
3110  int tmp = addnlocksup;
3111 
3112  addnlocksup = addnlocksdown;
3113  addnlocksdown = tmp;
3114  }
3115 
3116  lockvar = lockvar->data.aggregate.var;
3117  break;
3119  {
3120  int v;
3121 
3122  assert(!lockvar->donotmultaggr);
3123 
3124  for( v = lockvar->data.multaggr.nvars - 1; v >= 0; --v )
3125  {
3126  if( lockvar->data.multaggr.scalars[v] > 0.0 )
3127  {
3128  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, addnlocksdown,
3129  addnlocksup) );
3130  }
3131  else
3132  {
3133  SCIP_CALL( SCIPvarAddLocks(lockvar->data.multaggr.vars[v], blkmem, set, eventqueue, addnlocksup,
3134  addnlocksdown) );
3135  }
3136  }
3137  return SCIP_OKAY;
3138  }
3140  {
3141  int tmp = addnlocksup;
3142 
3143  assert(lockvar->negatedvar != NULL);
3144  assert(SCIPvarGetStatus(lockvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
3145  assert(lockvar->negatedvar->negatedvar == lockvar);
3146 
3147  addnlocksup = addnlocksdown;
3148  addnlocksdown = tmp;
3149 
3150  lockvar = lockvar->negatedvar;
3151  break;
3152  }
3153  default:
3154  SCIPerrorMessage("unknown variable status\n");
3155  return SCIP_INVALIDDATA;
3156  }
3157  }
3158 }
3159 
3160 /** gets number of locks for rounding down */
3162  SCIP_VAR* var /**< problem variable */
3163  )
3164 {
3165  int nlocks;
3166  int i;
3167 
3168  assert(var != NULL);
3169  assert(var->nlocksdown >= 0);
3170 
3171  switch( SCIPvarGetStatus(var) )
3172  {
3174  if( var->data.original.transvar != NULL )
3176  else
3177  return var->nlocksdown;
3178 
3179  case SCIP_VARSTATUS_LOOSE:
3180  case SCIP_VARSTATUS_COLUMN:
3181  case SCIP_VARSTATUS_FIXED:
3182  return var->nlocksdown;
3183 
3185  if( var->data.aggregate.scalar > 0.0 )
3186  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3187  else
3188  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3189 
3191  assert(!var->donotmultaggr);
3192  nlocks = 0;
3193  for( i = 0; i < var->data.multaggr.nvars; ++i )
3194  {
3195  if( var->data.multaggr.scalars[i] > 0.0 )
3196  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3197  else
3198  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3199  }
3200  return nlocks;
3201 
3203  assert(var->negatedvar != NULL);
3205  assert(var->negatedvar->negatedvar == var);
3206  return SCIPvarGetNLocksUp(var->negatedvar);
3207 
3208  default:
3209  SCIPerrorMessage("unknown variable status\n");
3210  SCIPABORT();
3211  return INT_MAX; /*lint !e527*/
3212  }
3213 }
3214 
3215 /** gets number of locks for rounding up */
3216 int SCIPvarGetNLocksUp(
3217  SCIP_VAR* var /**< problem variable */
3218  )
3219 {
3220  int nlocks;
3221  int i;
3222 
3223  assert(var != NULL);
3224  assert(var->nlocksup >= 0);
3225 
3226  switch( SCIPvarGetStatus(var) )
3227  {
3229  if( var->data.original.transvar != NULL )
3231  else
3232  return var->nlocksup;
3233 
3234  case SCIP_VARSTATUS_LOOSE:
3235  case SCIP_VARSTATUS_COLUMN:
3236  case SCIP_VARSTATUS_FIXED:
3237  return var->nlocksup;
3238 
3240  if( var->data.aggregate.scalar > 0.0 )
3241  return SCIPvarGetNLocksUp(var->data.aggregate.var);
3242  else
3243  return SCIPvarGetNLocksDown(var->data.aggregate.var);
3244 
3246  assert(!var->donotmultaggr);
3247  nlocks = 0;
3248  for( i = 0; i < var->data.multaggr.nvars; ++i )
3249  {
3250  if( var->data.multaggr.scalars[i] > 0.0 )
3251  nlocks += SCIPvarGetNLocksUp(var->data.multaggr.vars[i]);
3252  else
3253  nlocks += SCIPvarGetNLocksDown(var->data.multaggr.vars[i]);
3254  }
3255  return nlocks;
3256 
3258  assert(var->negatedvar != NULL);
3260  assert(var->negatedvar->negatedvar == var);
3261  return SCIPvarGetNLocksDown(var->negatedvar);
3262 
3263  default:
3264  SCIPerrorMessage("unknown variable status\n");
3265  SCIPABORT();
3266  return INT_MAX; /*lint !e527*/
3267  }
3268 }
3269 
3270 /** is it possible, to round variable down and stay feasible? */
3272  SCIP_VAR* var /**< problem variable */
3273  )
3274 {
3275  return (SCIPvarGetNLocksDown(var) == 0);
3276 }
3277 
3278 /** is it possible, to round variable up and stay feasible? */
3280  SCIP_VAR* var /**< problem variable */
3281  )
3282 {
3283  return (SCIPvarGetNLocksUp(var) == 0);
3284 }
3285 
3286 /** gets and captures transformed variable of a given variable; if the variable is not yet transformed,
3287  * a new transformed variable for this variable is created
3288  */
3290  SCIP_VAR* origvar, /**< original problem variable */
3291  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3292  SCIP_SET* set, /**< global SCIP settings */
3293  SCIP_STAT* stat, /**< problem statistics */
3294  SCIP_OBJSENSE objsense, /**< objective sense of original problem; transformed is always MINIMIZE */
3295  SCIP_VAR** transvar /**< pointer to store the transformed variable */
3296  )
3297 {
3298  char name[SCIP_MAXSTRLEN];
3299 
3300  assert(origvar != NULL);
3301  assert(origvar->scip == set->scip);
3302  assert(SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_ORIGINAL);
3303  assert(SCIPsetIsEQ(set, origvar->glbdom.lb, origvar->locdom.lb));
3304  assert(SCIPsetIsEQ(set, origvar->glbdom.ub, origvar->locdom.ub));
3305  assert(origvar->vlbs == NULL);
3306  assert(origvar->vubs == NULL);
3307  assert(transvar != NULL);
3308 
3309  /* check if variable is already transformed */
3310  if( origvar->data.original.transvar != NULL )
3311  {
3312  *transvar = origvar->data.original.transvar;
3313  SCIPvarCapture(*transvar);
3314  }
3315  else
3316  {
3317  /* create transformed variable */
3318  (void) SCIPsnprintf(name, SCIP_MAXSTRLEN, "t_%s", origvar->name);
3319  SCIP_CALL( SCIPvarCreateTransformed(transvar, blkmem, set, stat, name,
3320  origvar->glbdom.lb, origvar->glbdom.ub, (SCIP_Real)objsense * origvar->obj,
3321  SCIPvarGetType(origvar), origvar->initial, origvar->removable,
3322  origvar->vardelorig, origvar->vartrans, origvar->vardeltrans, origvar->varcopy, NULL) );
3323 
3324  /* copy the branch factor and priority */
3325  (*transvar)->branchfactor = origvar->branchfactor;
3326  (*transvar)->branchpriority = origvar->branchpriority;
3327  (*transvar)->branchdirection = origvar->branchdirection; /*lint !e732*/
3328 
3329  /* duplicate hole lists */
3330  SCIP_CALL( holelistDuplicate(&(*transvar)->glbdom.holelist, blkmem, set, origvar->glbdom.holelist) );
3331  SCIP_CALL( holelistDuplicate(&(*transvar)->locdom.holelist, blkmem, set, origvar->locdom.holelist) );
3332 
3333  /* link original and transformed variable */
3334  origvar->data.original.transvar = *transvar;
3335  SCIP_CALL( varAddParent(*transvar, blkmem, set, origvar) );
3336 
3337  /* copy rounding locks */
3338  (*transvar)->nlocksdown = origvar->nlocksdown;
3339  (*transvar)->nlocksup = origvar->nlocksup;
3340  assert((*transvar)->nlocksdown >= 0);
3341  assert((*transvar)->nlocksup >= 0);
3342 
3343  /* copy doNotMultiaggr status */
3344  (*transvar)->donotmultaggr = origvar->donotmultaggr;
3345 
3346  /* copy lazy bounds */
3347  (*transvar)->lazylb = origvar->lazylb;
3348  (*transvar)->lazyub = origvar->lazyub;
3349 
3350  /* transfer eventual variable statistics; do not update global statistics, because this has been done
3351  * when original variable was created
3352  */
3353  SCIPhistoryUnite((*transvar)->history, origvar->history, FALSE);
3354 
3355  /* transform user data */
3356  if( origvar->vartrans != NULL )
3357  {
3358  SCIP_CALL( origvar->vartrans(set->scip, origvar, origvar->vardata, *transvar, &(*transvar)->vardata) );
3359  }
3360  else
3361  (*transvar)->vardata = origvar->vardata;
3362  }
3363 
3364  SCIPsetDebugMsg(set, "transformed variable: <%s>[%p] -> <%s>[%p]\n", origvar->name, (void*)origvar, (*transvar)->name, (void*)*transvar);
3365 
3366  return SCIP_OKAY;
3367 }
3368 
3369 /** gets corresponding transformed variable of an original or negated original variable */
3371  SCIP_VAR* origvar, /**< original problem variable */
3372  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
3373  SCIP_SET* set, /**< global SCIP settings */
3374  SCIP_STAT* stat, /**< problem statistics */
3375  SCIP_VAR** transvar /**< pointer to store the transformed variable, or NULL if not existing yet */
3376  )
3377 {
3378  assert(origvar != NULL);
3380  assert(origvar->scip == set->scip);
3381 
3382  if( SCIPvarGetStatus(origvar) == SCIP_VARSTATUS_NEGATED )
3383  {
3384  assert(origvar->negatedvar != NULL);
3386 
3387  if( origvar->negatedvar->data.original.transvar == NULL )
3388  *transvar = NULL;
3389  else
3390  {
3391  SCIP_CALL( SCIPvarNegate(origvar->negatedvar->data.original.transvar, blkmem, set, stat, transvar) );
3392  }
3393  }
3394  else
3395  *transvar = origvar->data.original.transvar;
3396 
3397  return SCIP_OKAY;
3398 }
3399 
3400 /** converts loose transformed variable into column variable, creates LP column */
3402  SCIP_VAR* var, /**< problem variable */
3403  BMS_BLKMEM* blkmem, /**< block memory */
3404  SCIP_SET* set, /**< global SCIP settings */
3405  SCIP_STAT* stat, /**< problem statistics */
3406  SCIP_PROB* prob, /**< problem data */
3407  SCIP_LP* lp /**< current LP data */
3408  )
3409 {
3410  assert(var != NULL);
3411  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
3412  assert(var->scip == set->scip);
3413 
3414  SCIPsetDebugMsg(set, "creating column for variable <%s>\n", var->name);
3415 
3416  /* switch variable status */
3417  var->varstatus = SCIP_VARSTATUS_COLUMN; /*lint !e641*/
3418 
3419  /* create column of variable */
3420  SCIP_CALL( SCIPcolCreate(&var->data.col, blkmem, set, stat, var, 0, NULL, NULL, var->removable) );
3421 
3422  if( var->probindex != -1 )
3423  {
3424  /* inform problem about the variable's status change */
3425  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3426 
3427  /* inform LP, that problem variable is now a column variable and no longer loose */
3428  SCIP_CALL( SCIPlpUpdateVarColumn(lp, set, var) );
3429  }
3430 
3431  return SCIP_OKAY;
3432 }
3433 
3434 /** converts column transformed variable back into loose variable, frees LP column */
3436  SCIP_VAR* var, /**< problem variable */
3437  BMS_BLKMEM* blkmem, /**< block memory */
3438  SCIP_SET* set, /**< global SCIP settings */
3439  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3440  SCIP_PROB* prob, /**< problem data */
3441  SCIP_LP* lp /**< current LP data */
3442  )
3443 {
3444  assert(var != NULL);
3445  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
3446  assert(var->scip == set->scip);
3447  assert(var->data.col != NULL);
3448  assert(var->data.col->lppos == -1);
3449  assert(var->data.col->lpipos == -1);
3450 
3451  SCIPsetDebugMsg(set, "deleting column for variable <%s>\n", var->name);
3452 
3453  /* free column of variable */
3454  SCIP_CALL( SCIPcolFree(&var->data.col, blkmem, set, eventqueue, lp) );
3455 
3456  /* switch variable status */
3457  var->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
3458 
3459  if( var->probindex != -1 )
3460  {
3461  /* inform problem about the variable's status change */
3462  SCIP_CALL( SCIPprobVarChangedStatus(prob, blkmem, set, NULL, NULL, var) );
3463 
3464  /* inform LP, that problem variable is now a loose variable and no longer a column */
3465  SCIP_CALL( SCIPlpUpdateVarLoose(lp, set, var) );
3466  }
3467 
3468  return SCIP_OKAY;
3469 }
3470 
3471 /** issues a VARFIXED event on the given variable and all its parents (except ORIGINAL parents);
3472  * the event issuing on the parents is necessary, because unlike with bound changes, the parent variables
3473  * are not informed about a fixing of an active variable they are pointing to
3474  */
3475 static
3477  SCIP_VAR* var, /**< problem variable to change */
3478  BMS_BLKMEM* blkmem, /**< block memory */
3479  SCIP_SET* set, /**< global SCIP settings */
3480  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3481  int fixeventtype /**< is this event a fixation(0), an aggregation(1), or a
3482  * multi-aggregation(2)
3483  */
3484  )
3485 {
3486  SCIP_EVENT* event;
3487  SCIP_VARSTATUS varstatus;
3488  int i;
3489 
3490  assert(var != NULL);
3491  assert(var->scip == set->scip);
3492  assert(0 <= fixeventtype && fixeventtype <= 2);
3493 
3494  /* issue VARFIXED event on variable */
3495  SCIP_CALL( SCIPeventCreateVarFixed(&event, blkmem, var) );
3496  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
3497 
3498 #ifndef NDEBUG
3499  for( i = var->nparentvars -1; i >= 0; --i )
3500  {
3502  }
3503 #endif
3504 
3505  switch( fixeventtype )
3506  {
3507  case 0:
3508  /* process all parents of a fixed variable */
3509  for( i = var->nparentvars - 1; i >= 0; --i )
3510  {
3511  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3512 
3513  assert(varstatus != SCIP_VARSTATUS_FIXED);
3514 
3515  /* issue event on all not yet fixed parent variables, (that should already issued this event) except the original
3516  * one
3517  */
3518  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3519  {
3520  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3521  }
3522  }
3523  break;
3524  case 1:
3525  /* process all parents of a aggregated variable */
3526  for( i = var->nparentvars - 1; i >= 0; --i )
3527  {
3528  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3529 
3530  assert(varstatus != SCIP_VARSTATUS_FIXED);
3531 
3532  /* issue event for not aggregated parent variable, because for these and its parents the var event was already
3533  * issued(, except the original one)
3534  *
3535  * @note that even before an aggregated parent variable, there might be variables, for which the vent was not
3536  * yet issued
3537  */
3538  if( varstatus == SCIP_VARSTATUS_AGGREGATED )
3539  continue;
3540 
3541  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3542  {
3543  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3544  }
3545  }
3546  break;
3547  case 2:
3548  /* process all parents of a aggregated variable */
3549  for( i = var->nparentvars - 1; i >= 0; --i )
3550  {
3551  varstatus = SCIPvarGetStatus(var->parentvars[i]);
3552 
3553  assert(varstatus != SCIP_VARSTATUS_FIXED);
3554 
3555  /* issue event on all parent variables except the original one */
3556  if( varstatus != SCIP_VARSTATUS_ORIGINAL )
3557  {
3558  SCIP_CALL( varEventVarFixed(var->parentvars[i], blkmem, set, eventqueue, fixeventtype) );
3559  }
3560  }
3561  break;
3562  default:
3563  SCIPerrorMessage("unknown variable fixation event origin\n");
3564  return SCIP_INVALIDDATA;
3565  }
3566 
3567  return SCIP_OKAY;
3568 }
3569 
3570 /** converts variable into fixed variable */
3572  SCIP_VAR* var, /**< problem variable */
3573  BMS_BLKMEM* blkmem, /**< block memory */
3574  SCIP_SET* set, /**< global SCIP settings */
3575  SCIP_STAT* stat, /**< problem statistics */
3576  SCIP_PROB* transprob, /**< tranformed problem data */
3577  SCIP_PROB* origprob, /**< original problem data */
3578  SCIP_PRIMAL* primal, /**< primal data */
3579  SCIP_TREE* tree, /**< branch and bound tree */
3580  SCIP_REOPT* reopt, /**< reoptimization data structure */
3581  SCIP_LP* lp, /**< current LP data */
3582  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
3583  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
3584  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
3585  SCIP_Real fixedval, /**< value to fix variable at */
3586  SCIP_Bool* infeasible, /**< pointer to store whether the fixing is infeasible */
3587  SCIP_Bool* fixed /**< pointer to store whether the fixing was performed (variable was unfixed) */
3588  )
3589 {
3590  SCIP_Real obj;
3591  SCIP_Real childfixedval;
3592 
3593  assert(var != NULL);
3594  assert(var->scip == set->scip);
3595  assert(SCIPsetIsEQ(set, var->glbdom.lb, var->locdom.lb));
3596  assert(SCIPsetIsEQ(set, var->glbdom.ub, var->locdom.ub));
3597  assert(infeasible != NULL);
3598  assert(fixed != NULL);
3599 
3600  SCIPsetDebugMsg(set, "fix variable <%s>[%g,%g] to %g\n", var->name, var->glbdom.lb, var->glbdom.ub, fixedval);
3601 
3602  *infeasible = FALSE;
3603  *fixed = FALSE;
3604 
3606  {
3607  *infeasible = !SCIPsetIsFeasEQ(set, fixedval, var->locdom.lb);
3608  SCIPsetDebugMsg(set, " -> variable already fixed to %g (fixedval=%g): infeasible=%u\n", var->locdom.lb, fixedval, *infeasible);
3609  return SCIP_OKAY;
3610  }
3611  else if( (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && !SCIPsetIsFeasIntegral(set, fixedval))
3612  || SCIPsetIsFeasLT(set, fixedval, var->locdom.lb)
3613  || SCIPsetIsFeasGT(set, fixedval, var->locdom.ub) )
3614  {
3615  SCIPsetDebugMsg(set, " -> fixing infeasible: locdom=[%g,%g], fixedval=%g\n", var->locdom.lb, var->locdom.ub, fixedval);
3616  *infeasible = TRUE;
3617  return SCIP_OKAY;
3618  }
3619 
3620  switch( SCIPvarGetStatus(var) )
3621  {
3623  if( var->data.original.transvar == NULL )
3624  {
3625  SCIPerrorMessage("cannot fix an untransformed original variable\n");
3626  return SCIP_INVALIDDATA;
3627  }
3628  SCIP_CALL( SCIPvarFix(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
3629  lp, branchcand, eventqueue, cliquetable, fixedval, infeasible, fixed) );
3630  break;
3631 
3632  case SCIP_VARSTATUS_LOOSE:
3633  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
3634 
3635  /* set the fixed variable's objective value to 0.0 */
3636  obj = var->obj;
3637  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
3638 
3639  /* since we change the variable type form loose to fixed, we have to adjust the number of loose
3640  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
3641  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
3642  * objective of this variable is set to zero
3643  */
3644  SCIPlpDecNLoosevars(lp);
3645 
3646  /* change variable's bounds to fixed value (thereby removing redundant implications and variable bounds) */
3647  holelistFree(&var->glbdom.holelist, blkmem);
3648  holelistFree(&var->locdom.holelist, blkmem);
3649  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3650  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, fixedval) );
3651 
3652  /* explicitly set variable's bounds, even if the fixed value is in epsilon range of the old bound */
3653  var->glbdom.lb = fixedval;
3654  var->glbdom.ub = fixedval;
3655  var->locdom.lb = fixedval;
3656  var->locdom.ub = fixedval;
3657 
3658  /* delete implications and variable bounds information */
3659  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
3660  assert(var->vlbs == NULL);
3661  assert(var->vubs == NULL);
3662  assert(var->implics == NULL);
3663  assert(var->cliquelist == NULL);
3664 
3665  /* clear the history of the variable */
3666  SCIPhistoryReset(var->history);
3668 
3669  /* convert variable into fixed variable */
3670  var->varstatus = SCIP_VARSTATUS_FIXED; /*lint !e641*/
3671 
3672  /* inform problem about the variable's status change */
3673  if( var->probindex != -1 )
3674  {
3675  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
3676  }
3677 
3678  /* reset the objective value of the fixed variable, thus adjusting the problem's objective offset */
3679  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
3680 
3681  /* issue VARFIXED event */
3682  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 0) );
3683 
3684  *fixed = TRUE;
3685  break;
3686 
3687  case SCIP_VARSTATUS_COLUMN:
3688  SCIPerrorMessage("cannot fix a column variable\n");
3689  return SCIP_INVALIDDATA;
3690 
3691  case SCIP_VARSTATUS_FIXED:
3692  SCIPerrorMessage("cannot fix a fixed variable again\n"); /*lint !e527*/
3693  SCIPABORT(); /* case is already handled in earlier if condition */
3694  return SCIP_INVALIDDATA; /*lint !e527*/
3695 
3697  /* fix aggregation variable y in x = a*y + c, instead of fixing x directly */
3698  assert(SCIPsetIsZero(set, var->obj));
3699  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
3700  if( SCIPsetIsInfinity(set, fixedval) || SCIPsetIsInfinity(set, -fixedval) )
3701  childfixedval = (var->data.aggregate.scalar < 0.0 ? -fixedval : fixedval);
3702  else
3703  childfixedval = (fixedval - var->data.aggregate.constant)/var->data.aggregate.scalar;
3704  SCIP_CALL( SCIPvarFix(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3705  branchcand, eventqueue, cliquetable, childfixedval, infeasible, fixed) );
3706  break;
3707 
3709  SCIPerrorMessage("cannot fix a multiple aggregated variable\n");
3710  SCIPABORT();
3711  return SCIP_INVALIDDATA; /*lint !e527*/
3712 
3714  /* fix negation variable x in x' = offset - x, instead of fixing x' directly */
3715  assert(SCIPsetIsZero(set, var->obj));
3716  assert(var->negatedvar != NULL);
3718  assert(var->negatedvar->negatedvar == var);
3719  SCIP_CALL( SCIPvarFix(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
3720  branchcand, eventqueue, cliquetable, var->data.negate.constant - fixedval, infeasible, fixed) );
3721  break;
3722 
3723  default:
3724  SCIPerrorMessage("unknown variable status\n");
3725  return SCIP_INVALIDDATA;
3726  }
3727 
3728  return SCIP_OKAY;
3729 }
3730 
3731 /** transforms given variables, scalars and constant to the corresponding active variables, scalars and constant
3732  *
3733  * If the number of needed active variables is greater than the available slots in the variable array, nothing happens except
3734  * that the required size is stored in the corresponding variable; hence, if afterwards the required size is greater than the
3735  * available slots (varssize), nothing happens; otherwise, the active variable representation is stored in the arrays.
3736  *
3737  * The reason for this approach is that we cannot reallocate memory, since we do not know how the
3738  * memory has been allocated (e.g., by a C++ 'new' or SCIP functions).
3739  */
3741  SCIP_SET* set, /**< global SCIP settings */
3742  SCIP_VAR** vars, /**< variable array to get active variables */
3743  SCIP_Real* scalars, /**< scalars a_1, ..., a_n in linear sum a_1*x_1 + ... + a_n*x_n + c */
3744  int* nvars, /**< pointer to number of variables and values in vars and scalars array */
3745  int varssize, /**< available slots in vars and scalars array */
3746  SCIP_Real* constant, /**< pointer to constant c in linear sum a_1*x_1 + ... + a_n*x_n + c */
3747  int* requiredsize, /**< pointer to store the required array size for the active variables */
3748  SCIP_Bool mergemultiples /**< should multiple occurrences of a var be replaced by a single coeff? */
3749  )
3750 {
3751  SCIP_VAR** activevars;
3752  SCIP_Real* activescalars;
3753  int nactivevars;
3754  SCIP_Real activeconstant;
3755  SCIP_Bool activeconstantinf;
3756  int activevarssize;
3757 
3758  SCIP_VAR* var;
3759  SCIP_Real scalar;
3760  int v;
3761 
3762  SCIP_VAR** tmpvars;
3763  SCIP_VAR** multvars;
3764  SCIP_Real* tmpscalars;
3765  SCIP_Real* multscalars;
3766  int tmpvarssize;
3767  int ntmpvars;
3768  int nmultvars;
3769 
3770  SCIP_VAR* multvar;
3771  SCIP_Real multscalar;
3772  SCIP_Real multconstant;
3773  int pos;
3774 
3775  int noldtmpvars;
3776 
3777  SCIP_VAR** tmpvars2;
3778  SCIP_Real* tmpscalars2;
3779  int tmpvarssize2;
3780  int ntmpvars2;
3781 
3782  assert(set != NULL);
3783  assert(nvars != NULL);
3784  assert(scalars != NULL || *nvars == 0);
3785  assert(constant != NULL);
3786  assert(requiredsize != NULL);
3787  assert(*nvars <= varssize);
3788 
3789  *requiredsize = 0;
3790 
3791  if( *nvars == 0 )
3792  return SCIP_OKAY;
3793 
3794  assert(vars != NULL);
3795 
3796  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3797  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3798  {
3799  *requiredsize = 1;
3800 
3801  return SCIP_OKAY;
3802  }
3803 
3804  nactivevars = 0;
3805  activeconstant = 0.0;
3806  activeconstantinf = FALSE;
3807  activevarssize = (*nvars) * 2;
3808  ntmpvars = *nvars;
3809  tmpvarssize = *nvars;
3810 
3811  tmpvarssize2 = 1;
3812 
3813  /* allocate temporary memory */
3814  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3815  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3816  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3817  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3818  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3819  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3820 
3821  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3822  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3823  */
3824  for( v = ntmpvars - 1; v >= 0; --v )
3825  {
3826  var = tmpvars[v];
3827  scalar = tmpscalars[v];
3828 
3829  assert(var != NULL);
3830  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3831  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3832  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3833  */
3834  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3835  assert(var != NULL);
3836 
3837  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3838  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3839 
3840  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3841 
3842  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3843  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3846 
3847  tmpvars[v] = var;
3848  tmpscalars[v] = scalar;
3849  }
3850  noldtmpvars = ntmpvars;
3851 
3852  /* sort all variables to combine equal variables easily */
3853  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3854  for( v = ntmpvars - 1; v > 0; --v )
3855  {
3856  /* combine same variables */
3857  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
3858  {
3859  tmpscalars[v - 1] += tmpscalars[v];
3860  --ntmpvars;
3861  tmpvars[v] = tmpvars[ntmpvars];
3862  tmpscalars[v] = tmpscalars[ntmpvars];
3863  }
3864  }
3865  /* sort all variables again to combine equal variables later on */
3866  if( noldtmpvars > ntmpvars )
3867  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
3868 
3869  /* collect for each variable the representation in active variables */
3870  while( ntmpvars >= 1 )
3871  {
3872  --ntmpvars;
3873  ntmpvars2 = 0;
3874  var = tmpvars[ntmpvars];
3875  scalar = tmpscalars[ntmpvars];
3876 
3877  assert(var != NULL);
3878 
3879  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3880  if( scalar == 0.0 )
3881  continue;
3882 
3883  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3884  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3887 
3888  switch( SCIPvarGetStatus(var) )
3889  {
3890  case SCIP_VARSTATUS_LOOSE:
3891  case SCIP_VARSTATUS_COLUMN:
3892  /* x = a*y + c */
3893  if( nactivevars >= activevarssize )
3894  {
3895  activevarssize *= 2;
3896  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3897  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3898  assert(nactivevars < activevarssize);
3899  }
3900  activevars[nactivevars] = var;
3901  activescalars[nactivevars] = scalar;
3902  nactivevars++;
3903  break;
3904 
3906  /* x = a_1*y_1 + ... + a_n*y_n + c */
3907  nmultvars = var->data.multaggr.nvars;
3908  multvars = var->data.multaggr.vars;
3909  multscalars = var->data.multaggr.scalars;
3910 
3911  if( nmultvars + ntmpvars > tmpvarssize )
3912  {
3913  while( nmultvars + ntmpvars > tmpvarssize )
3914  tmpvarssize *= 2;
3915  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3916  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3917  assert(nmultvars + ntmpvars <= tmpvarssize);
3918  }
3919 
3920  if( nmultvars > tmpvarssize2 )
3921  {
3922  while( nmultvars > tmpvarssize2 )
3923  tmpvarssize2 *= 2;
3924  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3925  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3926  assert(nmultvars <= tmpvarssize2);
3927  }
3928 
3929  --nmultvars;
3930 
3931  for( ; nmultvars >= 0; --nmultvars )
3932  {
3933  multvar = multvars[nmultvars];
3934  multscalar = multscalars[nmultvars];
3935  multconstant = 0;
3936 
3937  assert(multvar != NULL);
3938  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
3939  assert(multvar != NULL);
3940 
3941  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3942  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3945 
3946  if( !activeconstantinf )
3947  {
3948  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
3949 
3950  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
3951  {
3952  assert(scalar != 0.0);
3953  if( scalar * multconstant > 0.0 )
3954  {
3955  activeconstant = SCIPsetInfinity(set);
3956  activeconstantinf = TRUE;
3957  }
3958  else
3959  {
3960  activeconstant = -SCIPsetInfinity(set);
3961  activeconstantinf = TRUE;
3962  }
3963  }
3964  else
3965  activeconstant += scalar * multconstant;
3966  }
3967 #ifndef NDEBUG
3968  else
3969  {
3970  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
3971  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3972  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
3973  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3974  }
3975 #endif
3976 
3977  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
3978  {
3979  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
3980  tmpscalars[pos] += scalar * multscalar;
3981  }
3982  else
3983  {
3984  tmpvars2[ntmpvars2] = multvar;
3985  tmpscalars2[ntmpvars2] = scalar * multscalar;
3986  ++(ntmpvars2);
3987  assert(ntmpvars2 <= tmpvarssize2);
3988  }
3989  }
3990 
3991  /* sort all variables to combine equal variables easily */
3992  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
3993  for( v = ntmpvars2 - 1; v > 0; --v )
3994  {
3995  /* combine same variables */
3996  if( SCIPvarCompare(tmpvars2[v], tmpvars2[v - 1]) == 0 )
3997  {
3998  tmpscalars2[v - 1] += tmpscalars2[v];
3999  --ntmpvars2;
4000  tmpvars2[v] = tmpvars2[ntmpvars2];
4001  tmpscalars2[v] = tmpscalars2[ntmpvars2];
4002  }
4003  }
4004 
4005  for( v = 0; v < ntmpvars2; ++v )
4006  {
4007  tmpvars[ntmpvars] = tmpvars2[v];
4008  tmpscalars[ntmpvars] = tmpscalars2[v];
4009  ++(ntmpvars);
4010  assert(ntmpvars <= tmpvarssize);
4011  }
4012  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, ntmpvars);
4013 
4014  if( !activeconstantinf )
4015  {
4016  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4017 
4018  multconstant = SCIPvarGetMultaggrConstant(var);
4019 
4020  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4021  {
4022  assert(scalar != 0.0);
4023  if( scalar * multconstant > 0.0 )
4024  {
4025  activeconstant = SCIPsetInfinity(set);
4026  activeconstantinf = TRUE;
4027  }
4028  else
4029  {
4030  activeconstant = -SCIPsetInfinity(set);
4031  activeconstantinf = TRUE;
4032  }
4033  }
4034  else
4035  activeconstant += scalar * multconstant;
4036  }
4037 #ifndef NDEBUG
4038  else
4039  {
4040  multconstant = SCIPvarGetMultaggrConstant(var);
4041  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4042  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4043  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4044  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4045  }
4046 #endif
4047  break;
4048 
4049  case SCIP_VARSTATUS_FIXED:
4053  default:
4054  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4055  * fixed variables and is handled already
4056  */
4057  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4058  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4059  }
4060  }
4061 
4062  if( mergemultiples )
4063  {
4064  /* sort variable and scalar array by variable index */
4065  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4066 
4067  /* eliminate duplicates and count required size */
4068  v = nactivevars - 1;
4069  while( v > 0 )
4070  {
4071  /* combine both variable since they are the same */
4072  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4073  {
4074  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4075  {
4076  activescalars[v - 1] += activescalars[v];
4077  --nactivevars;
4078  activevars[v] = activevars[nactivevars];
4079  activescalars[v] = activescalars[nactivevars];
4080  }
4081  else
4082  {
4083  --nactivevars;
4084  activevars[v] = activevars[nactivevars];
4085  activescalars[v] = activescalars[nactivevars];
4086  --nactivevars;
4087  --v;
4088  activevars[v] = activevars[nactivevars];
4089  activescalars[v] = activescalars[nactivevars];
4090  }
4091  }
4092  --v;
4093  }
4094  }
4095  *requiredsize = nactivevars;
4096 
4097  if( varssize >= *requiredsize )
4098  {
4099  assert(vars != NULL);
4100 
4101  *nvars = *requiredsize;
4102 
4103  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4104  {
4105  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4106  if( activeconstantinf )
4107  (*constant) = activeconstant;
4108  else
4109  (*constant) += activeconstant;
4110  }
4111 #ifndef NDEBUG
4112  else
4113  {
4114  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4115  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4116  }
4117 #endif
4118 
4119  /* copy active variable and scalar array to the given arrays */
4120  for( v = 0; v < *nvars; ++v )
4121  {
4122  vars[v] = activevars[v];
4123  scalars[v] = activescalars[v]; /*lint !e613*/
4124  }
4125  }
4126 
4127  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4128  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4129 
4130  SCIPsetFreeBufferArray(set, &tmpscalars);
4131  SCIPsetFreeBufferArray(set, &tmpvars);
4132  SCIPsetFreeBufferArray(set, &activescalars);
4133  SCIPsetFreeBufferArray(set, &activevars);
4134  SCIPsetFreeBufferArray(set, &tmpscalars2);
4135  SCIPsetFreeBufferArray(set, &tmpvars2);
4136 
4137  return SCIP_OKAY;
4138 }
4139 
4140 
4141 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4143  SCIP_VAR* var, /**< problem variable */
4144  BMS_BLKMEM* blkmem, /**< block memory */
4145  SCIP_SET* set /**< global SCIP settings */
4146  )
4147 {
4148  SCIP_Real multconstant;
4149  int multvarssize;
4150  int nmultvars;
4151  int multrequiredsize;
4152 
4153  assert( var != NULL );
4154  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4155  assert(var->scip == set->scip);
4156 
4157  multconstant = var->data.multaggr.constant;
4158  nmultvars = var->data.multaggr.nvars;
4159  multvarssize = var->data.multaggr.varssize;
4160 
4161  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4162 
4163  if( multrequiredsize > multvarssize )
4164  {
4165  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4166  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4167  multvarssize = multrequiredsize;
4168  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4169  assert( multrequiredsize <= multvarssize );
4170  }
4171  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4172  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4173  * may loose performance hereby, since aggregated variables are easier to handle.
4174  *
4175  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4176  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4177  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4178  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4179  *
4180  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4181  *
4182  * The same issue appears in the SCIPvarGetProbvar...() methods.
4183  */
4184 
4185  var->data.multaggr.constant = multconstant;
4186  var->data.multaggr.nvars = nmultvars;
4187  var->data.multaggr.varssize = multvarssize;
4188 
4189  return SCIP_OKAY;
4190 }
4191 
4192 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4193  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4194  * the history merge is reasonable
4195  *
4196  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4197  * this corrupts the variable pseudo costs
4198  * @note Apply with care; no internal checks are performed if the two variables should be merged
4199  */
4201  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4202  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4203  SCIP_STAT* stat /**< problem statistics */
4204  )
4205 {
4206  /* merge only the history of the current run into the target history */
4207  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4208 
4209  /* apply the changes also to the global history */
4210  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4211 }
4212 
4213 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4214  * history over several iterations
4215  */
4216 void SCIPvarSetHistory(
4217  SCIP_VAR* var, /**< variable */
4218  SCIP_HISTORY* history, /**< the history which is to set */
4219  SCIP_STAT* stat /**< problem statistics */
4220  )
4221 {
4222  /* merge only the history of the current run into the target history */
4223  SCIPhistoryUnite(var->history, history, FALSE);
4224 
4225  /* apply the changes also to the global history */
4226  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4227 }
4228 
4229 /** tightens the bounds of both variables in aggregation x = a*y + c */
4230 static
4232  SCIP_VAR* var, /**< problem variable */
4233  BMS_BLKMEM* blkmem, /**< block memory */
4234  SCIP_SET* set, /**< global SCIP settings */
4235  SCIP_STAT* stat, /**< problem statistics */
4236  SCIP_PROB* transprob, /**< tranformed problem data */
4237  SCIP_PROB* origprob, /**< original problem data */
4238  SCIP_PRIMAL* primal, /**< primal data */
4239  SCIP_TREE* tree, /**< branch and bound tree */
4240  SCIP_REOPT* reopt, /**< reoptimization data structure */
4241  SCIP_LP* lp, /**< current LP data */
4242  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4243  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4244  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4245  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4246  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4247  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4248  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4249  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4250  )
4251 {
4252  SCIP_Real varlb;
4253  SCIP_Real varub;
4254  SCIP_Real aggvarlb;
4255  SCIP_Real aggvarub;
4256  SCIP_Bool aggvarbdschanged;
4257 
4258  assert(var != NULL);
4259  assert(var->scip == set->scip);
4260  assert(aggvar != NULL);
4261  assert(!SCIPsetIsZero(set, scalar));
4262  assert(infeasible != NULL);
4263  assert(fixed != NULL);
4264 
4265  *infeasible = FALSE;
4266  *fixed = FALSE;
4267 
4268  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4269  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4270  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4271 
4272  /* loop as long additional changes may be found */
4273  do
4274  {
4275  aggvarbdschanged = FALSE;
4276 
4277  /* update the bounds of the aggregated variable x in x = a*y + c */
4278  if( scalar > 0.0 )
4279  {
4280  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4281  varlb = -SCIPsetInfinity(set);
4282  else
4283  varlb = aggvar->glbdom.lb * scalar + constant;
4284  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4285  varub = SCIPsetInfinity(set);
4286  else
4287  varub = aggvar->glbdom.ub * scalar + constant;
4288  }
4289  else
4290  {
4291  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4292  varub = SCIPsetInfinity(set);
4293  else
4294  varub = aggvar->glbdom.lb * scalar + constant;
4295  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4296  varlb = -SCIPsetInfinity(set);
4297  else
4298  varlb = aggvar->glbdom.ub * scalar + constant;
4299  }
4300  varlb = MAX(varlb, var->glbdom.lb);
4301  varub = MIN(varub, var->glbdom.ub);
4302  SCIPvarAdjustLb(var, set, &varlb);
4303  SCIPvarAdjustUb(var, set, &varub);
4304 
4305  /* check the new bounds */
4306  if( SCIPsetIsGT(set, varlb, varub) )
4307  {
4308  /* the aggregation is infeasible */
4309  *infeasible = TRUE;
4310  return SCIP_OKAY;
4311  }
4312  else if( SCIPsetIsEQ(set, varlb, varub) )
4313  {
4314  /* the aggregated variable is fixed -> fix both variables */
4315  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4316  eventqueue, cliquetable, varlb, infeasible, fixed) );
4317  if( !(*infeasible) )
4318  {
4319  SCIP_Bool aggfixed;
4320 
4321  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4322  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4323  assert(*fixed == aggfixed);
4324  }
4325  return SCIP_OKAY;
4326  }
4327  else
4328  {
4329  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4330  {
4331  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4332  }
4333  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4334  {
4335  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4336  }
4337 
4338  /* update the hole list of the aggregation variable */
4339  /**@todo update hole list of aggregation variable */
4340  }
4341 
4342  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4343  if( scalar > 0.0 )
4344  {
4345  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4346  aggvarlb = -SCIPsetInfinity(set);
4347  else
4348  aggvarlb = (var->glbdom.lb - constant) / scalar;
4349  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4350  aggvarub = SCIPsetInfinity(set);
4351  else
4352  aggvarub = (var->glbdom.ub - constant) / scalar;
4353  }
4354  else
4355  {
4356  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4357  aggvarub = SCIPsetInfinity(set);
4358  else
4359  aggvarub = (var->glbdom.lb - constant) / scalar;
4360  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4361  aggvarlb = -SCIPsetInfinity(set);
4362  else
4363  aggvarlb = (var->glbdom.ub - constant) / scalar;
4364  }
4365  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4366  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4367  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4368  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4369 
4370  /* check the new bounds */
4371  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4372  {
4373  /* the aggregation is infeasible */
4374  *infeasible = TRUE;
4375  return SCIP_OKAY;
4376  }
4377  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4378  {
4379  /* the aggregation variable is fixed -> fix both variables */
4380  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4381  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4382  if( !(*infeasible) )
4383  {
4384  SCIP_Bool varfixed;
4385 
4386  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4387  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4388  assert(*fixed == varfixed);
4389  }
4390  return SCIP_OKAY;
4391  }
4392  else
4393  {
4394  SCIP_Real oldbd;
4395  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4396  {
4397  oldbd = aggvar->glbdom.lb;
4398  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4399  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4400  }
4401  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4402  {
4403  oldbd = aggvar->glbdom.ub;
4404  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4405  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4406  }
4407 
4408  /* update the hole list of the aggregation variable */
4409  /**@todo update hole list of aggregation variable */
4410  }
4411  }
4412  while( aggvarbdschanged );
4413 
4414  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4415  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4416 
4417  return SCIP_OKAY;
4418 }
4419 
4420 /** converts loose variable into aggregated variable */
4422  SCIP_VAR* var, /**< loose problem variable */
4423  BMS_BLKMEM* blkmem, /**< block memory */
4424  SCIP_SET* set, /**< global SCIP settings */
4425  SCIP_STAT* stat, /**< problem statistics */
4426  SCIP_PROB* transprob, /**< tranformed problem data */
4427  SCIP_PROB* origprob, /**< original problem data */
4428  SCIP_PRIMAL* primal, /**< primal data */
4429  SCIP_TREE* tree, /**< branch and bound tree */
4430  SCIP_REOPT* reopt, /**< reoptimization data structure */
4431  SCIP_LP* lp, /**< current LP data */
4432  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4433  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4434  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4435  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4436  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4437  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4438  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4439  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4440  )
4441 {
4442  SCIP_VAR** vars;
4443  SCIP_Real* coefs;
4444  SCIP_Real* constants;
4445  SCIP_Real obj;
4446  SCIP_Real branchfactor;
4447  SCIP_Bool fixed;
4448  int branchpriority;
4449  int nlocksdown;
4450  int nlocksup;
4451  int nvbds;
4452  int i;
4453  int j;
4454 
4455  assert(var != NULL);
4456  assert(aggvar != NULL);
4457  assert(var->scip == set->scip);
4458  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4459  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4460  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4461  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4462  assert(infeasible != NULL);
4463  assert(aggregated != NULL);
4464 
4465  *infeasible = FALSE;
4466  *aggregated = FALSE;
4467 
4468  /* get active problem variable of aggregation variable */
4469  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4470 
4471  /* aggregation is a fixing, if the scalar is zero */
4472  if( SCIPsetIsZero(set, scalar) )
4473  {
4474  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4475  cliquetable, constant, infeasible, aggregated) );
4476  return SCIP_OKAY;
4477  }
4478 
4479  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4480  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4481  return SCIP_OKAY;
4482 
4483  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4484  * should be changed in the future
4485  */
4486  if( SCIPvarGetHolelistGlobal(var) != NULL )
4487  return SCIP_OKAY;
4488 
4489  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4490  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4491  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4492 
4493  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4494  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4495 
4496  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4497  if( var == aggvar )
4498  {
4499  if( SCIPsetIsEQ(set, scalar, 1.0) )
4500  *infeasible = !SCIPsetIsZero(set, constant);
4501  else
4502  {
4503  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4504  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4505  }
4506  return SCIP_OKAY;
4507  }
4508 
4509  /* tighten the bounds of aggregated and aggregation variable */
4510  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4511  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4512  if( *infeasible || fixed )
4513  {
4514  *aggregated = fixed;
4515  return SCIP_OKAY;
4516  }
4517 
4518  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4519  * aggregated variable
4520  */
4521  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4522  assert(var->cliquelist == NULL);
4523 
4524  /* set the aggregated variable's objective value to 0.0 */
4525  obj = var->obj;
4526  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4527 
4528  /* unlock all rounding locks */
4529  nlocksdown = var->nlocksdown;
4530  nlocksup = var->nlocksup;
4531  var->nlocksdown = 0;
4532  var->nlocksup = 0;
4533 
4534  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4535  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4536  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4537  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4538  {
4539  /* link both variables as negation pair */
4540  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4541  var->data.negate.constant = 1.0;
4542  var->negatedvar = aggvar;
4543  aggvar->negatedvar = var;
4544 
4545  /* copy doNotMultiaggr status */
4546  aggvar->donotmultaggr |= var->donotmultaggr;
4547 
4548  /* mark both variables to be non-deletable */
4550  SCIPvarMarkNotDeletable(aggvar);
4551  }
4552  else
4553  {
4554  /* convert variable into aggregated variable */
4555  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4556  var->data.aggregate.var = aggvar;
4557  var->data.aggregate.scalar = scalar;
4558  var->data.aggregate.constant = constant;
4559 
4560  /* copy doNotMultiaggr status */
4561  aggvar->donotmultaggr |= var->donotmultaggr;
4562 
4563  /* mark both variables to be non-deletable */
4565  SCIPvarMarkNotDeletable(aggvar);
4566  }
4567 
4568  /* make aggregated variable a parent of the aggregation variable */
4569  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4570 
4571  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variable */
4572  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
4573 
4574  /* move the variable bounds to the aggregation variable:
4575  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4576  * - free the variable bounds data structures
4577  */
4578  if( var->vlbs != NULL )
4579  {
4580  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4581  vars = SCIPvboundsGetVars(var->vlbs);
4582  coefs = SCIPvboundsGetCoefs(var->vlbs);
4583  constants = SCIPvboundsGetConstants(var->vlbs);
4584  for( i = 0; i < nvbds && !(*infeasible); ++i )
4585  {
4586  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4587  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4588  }
4589  }
4590  if( var->vubs != NULL )
4591  {
4592  nvbds = SCIPvboundsGetNVbds(var->vubs);
4593  vars = SCIPvboundsGetVars(var->vubs);
4594  coefs = SCIPvboundsGetCoefs(var->vubs);
4595  constants = SCIPvboundsGetConstants(var->vubs);
4596  for( i = 0; i < nvbds && !(*infeasible); ++i )
4597  {
4598  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4599  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4600  }
4601  }
4602  SCIPvboundsFree(&var->vlbs, blkmem);
4603  SCIPvboundsFree(&var->vubs, blkmem);
4604 
4605  /* move the implications to the aggregation variable:
4606  * - add all implications again to the variable, thus adding it to the aggregation variable
4607  * - free the implications data structures
4608  */
4609  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4610  {
4611  assert(SCIPvarIsBinary(var));
4612  for( i = 0; i < 2; ++i )
4613  {
4614  SCIP_VAR** implvars;
4615  SCIP_BOUNDTYPE* impltypes;
4616  SCIP_Real* implbounds;
4617  int nimpls;
4618 
4619  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4620  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4621  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4622  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4623 
4624  for( j = 0; j < nimpls && !(*infeasible); ++j )
4625  {
4626  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4627  * implication to the aggregated variable?
4628  */
4629  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4630  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4631  NULL) );
4632  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4633  }
4634  }
4635  }
4636  SCIPimplicsFree(&var->implics, blkmem);
4637 
4638  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4639  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4640  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4641  SCIPhistoryReset(var->history);
4643 
4644  /* update flags of aggregation variable */
4645  aggvar->removable &= var->removable;
4646 
4647  /* update branching factors and priorities of both variables to be the maximum of both variables */
4648  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4649  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4650  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4651  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4652  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4653  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4654 
4655  /* update branching direction of both variables to agree to a single direction */
4656  if( scalar >= 0.0 )
4657  {
4659  {
4661  }
4662  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4663  {
4665  }
4666  else if( var->branchdirection != aggvar->branchdirection )
4667  {
4669  }
4670  }
4671  else
4672  {
4674  {
4676  }
4677  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4678  {
4680  }
4681  else if( var->branchdirection != aggvar->branchdirection )
4682  {
4684  }
4685  }
4686 
4687  if( var->probindex != -1 )
4688  {
4689  /* inform problem about the variable's status change */
4690  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4691  }
4692 
4693  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4694  * variable and the problem's objective offset
4695  */
4696  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4697 
4698  /* issue VARFIXED event */
4699  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4700 
4701  *aggregated = TRUE;
4702 
4703  return SCIP_OKAY;
4704 }
4705 
4706 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4707  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4708  *
4709  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4710  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4711  */
4712 static
4714  SCIP_SET* set, /**< global SCIP settings */
4715  BMS_BLKMEM* blkmem, /**< block memory */
4716  SCIP_STAT* stat, /**< problem statistics */
4717  SCIP_PROB* transprob, /**< tranformed problem data */
4718  SCIP_PROB* origprob, /**< original problem data */
4719  SCIP_PRIMAL* primal, /**< primal data */
4720  SCIP_TREE* tree, /**< branch and bound tree */
4721  SCIP_REOPT* reopt, /**< reoptimization data structure */
4722  SCIP_LP* lp, /**< current LP data */
4723  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4724  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4725  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4726  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4727  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4728  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4729  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4730  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4731  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4732  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4733  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4734  )
4735 {
4736  SCIP_VAR* aggvar;
4737  char aggvarname[SCIP_MAXSTRLEN];
4738  SCIP_Longint scalarxn = 0;
4739  SCIP_Longint scalarxd = 0;
4740  SCIP_Longint scalaryn = 0;
4741  SCIP_Longint scalaryd = 0;
4742  SCIP_Longint a;
4743  SCIP_Longint b;
4744  SCIP_Longint c;
4745  SCIP_Longint scm;
4746  SCIP_Longint gcd;
4747  SCIP_Longint currentclass;
4748  SCIP_Longint classstep;
4749  SCIP_Longint xsol;
4750  SCIP_Longint ysol;
4751  SCIP_Bool success;
4752  SCIP_VARTYPE vartype;
4753 
4754 #define MAXDNOM 1000000LL
4755 
4756  assert(set != NULL);
4757  assert(blkmem != NULL);
4758  assert(stat != NULL);
4759  assert(transprob != NULL);
4760  assert(origprob != NULL);
4761  assert(tree != NULL);
4762  assert(lp != NULL);
4763  assert(cliquetable != NULL);
4764  assert(branchcand != NULL);
4765  assert(eventqueue != NULL);
4766  assert(varx != NULL);
4767  assert(vary != NULL);
4768  assert(varx != vary);
4769  assert(infeasible != NULL);
4770  assert(aggregated != NULL);
4771  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4772  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4774  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4776  assert(!SCIPsetIsZero(set, scalarx));
4777  assert(!SCIPsetIsZero(set, scalary));
4778 
4779  *infeasible = FALSE;
4780  *aggregated = FALSE;
4781 
4782  /* get rational representation of coefficients */
4783  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4784  if( success )
4785  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4786  if( !success )
4787  return SCIP_OKAY;
4788  assert(scalarxd >= 1);
4789  assert(scalaryd >= 1);
4790 
4791  /* multiply equality with smallest common denominator */
4792  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4793  a = (scm/scalarxd)*scalarxn;
4794  b = (scm/scalaryd)*scalaryn;
4795  rhs *= scm;
4796 
4797  /* divide equality by the greatest common divisor of a and b */
4798  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4799  a /= gcd;
4800  b /= gcd;
4801  rhs /= gcd;
4802  assert(a != 0);
4803  assert(b != 0);
4804 
4805  /* check, if right hand side is integral */
4806  if( !SCIPsetIsFeasIntegral(set, rhs) )
4807  {
4808  *infeasible = TRUE;
4809  return SCIP_OKAY;
4810  }
4811  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4812 
4813  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4814  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4815  {
4816  /* aggregate x = - b/a*y + c/a */
4817  /*lint --e{653}*/
4818  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4819  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4820  assert(*aggregated);
4821  return SCIP_OKAY;
4822  }
4823  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4824  {
4825  /* aggregate y = - a/b*x + c/b */
4826  /*lint --e{653}*/
4827  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4828  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4829  assert(*aggregated);
4830  return SCIP_OKAY;
4831  }
4832 
4833  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4834  * common divisor. Let (x',y') be a solution of the equality
4835  * a*x + b*y == c -> a*x == c - b*y
4836  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4837  */
4838 
4839  /* find initial solution (x',y'):
4840  * - find y' such that c - b*y' is a multiple of a
4841  * - start in equivalence class c%a
4842  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
4843  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
4844  * - 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
4845  * - calculate x' with x' = (c - b*y')/a (which must be integral)
4846  *
4847  * Algorithm works for a > 0 only.
4848  */
4849  if( a < 0 )
4850  {
4851  a = -a;
4852  b = -b;
4853  c = -c;
4854  }
4855  assert(0 <= a);
4856 
4857  /* search upwards from ysol = 0 */
4858  ysol = 0;
4859  currentclass = c%a;
4860  if( currentclass < 0 )
4861  currentclass += a;
4862  assert(0 <= currentclass && currentclass < a);
4863 
4864  classstep = (-b)%a;
4865 
4866  if( classstep < 0 )
4867  classstep += a;
4868  assert(0 <= classstep && classstep < a);
4869 
4870  while( currentclass != 0 )
4871  {
4872  assert(0 <= currentclass && currentclass < a);
4873  currentclass += classstep;
4874  if( currentclass >= a )
4875  currentclass -= a;
4876  ysol++;
4877  }
4878  assert(ysol < a);
4879  assert(((c - b*ysol)%a) == 0);
4880 
4881  xsol = (c - b*ysol)/a;
4882 
4883  /* determine variable type for new artificial variable:
4884  *
4885  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
4886  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
4887  * integral type
4888  */
4891 
4892  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
4893  * - create new integer variable z with infinite bounds
4894  * - aggregate variable x = -b*z + x'
4895  * - aggregate variable y = a*z + y'
4896  * - the bounds of z are calculated automatically during aggregation
4897  */
4898  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
4899  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
4900  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
4902  NULL, NULL, NULL, NULL, NULL) );
4903 
4904  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
4905 
4906  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4907  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
4908  assert(*aggregated || *infeasible);
4909 
4910  if( !(*infeasible) )
4911  {
4912  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4913  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
4914  assert(*aggregated || *infeasible);
4915  }
4916 
4917  /* release z */
4918  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
4919 
4920  return SCIP_OKAY;
4921 }
4922 
4923 /** performs second step of SCIPaggregateVars():
4924  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
4925  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
4926  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
4927  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
4928  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
4929  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4930  *
4931  * @todo check for fixings, infeasibility, bound changes, or domain holes:
4932  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
4933  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
4934  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
4935  */
4937  SCIP_SET* set, /**< global SCIP settings */
4938  BMS_BLKMEM* blkmem, /**< block memory */
4939  SCIP_STAT* stat, /**< problem statistics */
4940  SCIP_PROB* transprob, /**< tranformed problem data */
4941  SCIP_PROB* origprob, /**< original problem data */
4942  SCIP_PRIMAL* primal, /**< primal data */
4943  SCIP_TREE* tree, /**< branch and bound tree */
4944  SCIP_REOPT* reopt, /**< reoptimization data structure */
4945  SCIP_LP* lp, /**< current LP data */
4946  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4947  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4948  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4949  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4950  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
4951  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
4952  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4953  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4954  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4955  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4956  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4957  )
4958 {
4959  SCIP_Bool easyaggr;
4960  SCIP_Real maxscalar;
4961  SCIP_Real absquot;
4962 
4963  assert(set != NULL);
4964  assert(blkmem != NULL);
4965  assert(stat != NULL);
4966  assert(transprob != NULL);
4967  assert(origprob != NULL);
4968  assert(tree != NULL);
4969  assert(lp != NULL);
4970  assert(cliquetable != NULL);
4971  assert(branchcand != NULL);
4972  assert(eventqueue != NULL);
4973  assert(varx != NULL);
4974  assert(vary != NULL);
4975  assert(varx != vary);
4976  assert(infeasible != NULL);
4977  assert(aggregated != NULL);
4978  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4979  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4980  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4981  assert(!SCIPsetIsZero(set, scalarx));
4982  assert(!SCIPsetIsZero(set, scalary));
4983 
4984  *infeasible = FALSE;
4985  *aggregated = FALSE;
4986 
4987  absquot = REALABS(scalarx / scalary);
4988  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
4989  maxscalar = MAX(maxscalar, 1.0);
4990 
4991  if( absquot > maxscalar || absquot < 1 / maxscalar )
4992  return SCIP_OKAY;
4993 
4994  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
4995  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
4996  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
4997  {
4998  SCIP_VAR* var;
4999  SCIP_Real scalar;
5000 
5001  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5002  var = vary;
5003  vary = varx;
5004  varx = var;
5005  scalar = scalary;
5006  scalary = scalarx;
5007  scalarx = scalar;
5008  }
5009 
5010  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5011  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5012  return SCIP_OKAY;
5013 
5014  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5015 
5016  /* figure out, which variable should be aggregated */
5017  easyaggr = FALSE;
5018 
5019  /* check if it is an easy aggregation that means:
5020  *
5021  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5022  */
5023  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5024  {
5026  {
5027  easyaggr = TRUE;
5028  }
5029  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5030  {
5031  easyaggr = TRUE;
5032  }
5033  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5034  {
5035  /* we have an easy aggregation if we flip the variables x and y */
5036  SCIP_VAR* var;
5037  SCIP_Real scalar;
5038 
5039  /* switch the variables, such that varx is the aggregated variable */
5040  var = vary;
5041  vary = varx;
5042  varx = var;
5043  scalar = scalary;
5044  scalary = scalarx;
5045  scalarx = scalar;
5046  easyaggr = TRUE;
5047  }
5048  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5049  {
5050  /* the aggregation is still easy if both variables are continuous */
5051  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5052  easyaggr = TRUE;
5053  }
5054  }
5055 
5056  /* did we find an "easy" aggregation? */
5057  if( easyaggr )
5058  {
5059  SCIP_Real scalar;
5060  SCIP_Real constant;
5061 
5062  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5063 
5064  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5065  scalar = -scalary/scalarx;
5066  constant = rhs/scalarx;
5067 
5068  /* check aggregation for integer feasibility */
5071  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5072  {
5073  *infeasible = TRUE;
5074  return SCIP_OKAY;
5075  }
5076 
5077  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5078  * since then we would loose the corresponding divisibility property
5079  */
5080  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5081 
5082  /* aggregate the variable */
5083  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5084  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5085  assert(*aggregated || *infeasible);
5086  }
5089  {
5090  /* the variables are both integral: we have to try to find an integer aggregation */
5091  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5092  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5093  }
5094 
5095  return SCIP_OKAY;
5096 }
5097 
5098 /** converts variable into multi-aggregated variable */
5100  SCIP_VAR* var, /**< problem variable */
5101  BMS_BLKMEM* blkmem, /**< block memory */
5102  SCIP_SET* set, /**< global SCIP settings */
5103  SCIP_STAT* stat, /**< problem statistics */
5104  SCIP_PROB* transprob, /**< tranformed problem data */
5105  SCIP_PROB* origprob, /**< original problem data */
5106  SCIP_PRIMAL* primal, /**< primal data */
5107  SCIP_TREE* tree, /**< branch and bound tree */
5108  SCIP_REOPT* reopt, /**< reoptimization data structure */
5109  SCIP_LP* lp, /**< current LP data */
5110  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5111  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5112  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5113  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5114  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5115  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5116  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5117  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5118  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5119  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5120  )
5121 {
5122  SCIP_VAR** tmpvars;
5123  SCIP_Real* tmpscalars;
5124  SCIP_Real obj;
5125  SCIP_Real branchfactor;
5126  int branchpriority;
5127  SCIP_BRANCHDIR branchdirection;
5128  int nlocksdown;
5129  int nlocksup;
5130  int v;
5131  SCIP_Real tmpconstant;
5132  SCIP_Real tmpscalar;
5133  int ntmpvars;
5134  int tmpvarssize;
5135  int tmprequiredsize;
5136 
5137  assert(var != NULL);
5138  assert(var->scip == set->scip);
5139  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5140  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5141  assert(naggvars == 0 || aggvars != NULL);
5142  assert(naggvars == 0 || scalars != NULL);
5143  assert(infeasible != NULL);
5144  assert(aggregated != NULL);
5145 
5146  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5147 
5148  *infeasible = FALSE;
5149  *aggregated = FALSE;
5150 
5151  switch( SCIPvarGetStatus(var) )
5152  {
5154  if( var->data.original.transvar == NULL )
5155  {
5156  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5157  return SCIP_INVALIDDATA;
5158  }
5159  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5160  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5161  break;
5162 
5163  case SCIP_VARSTATUS_LOOSE:
5164  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5165 
5166  /* check if we would create a self-reference */
5167  ntmpvars = naggvars;
5168  tmpvarssize = naggvars;
5169  tmpconstant = constant;
5170  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5171  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5172 
5173  /* get all active variables for multi-aggregation */
5174  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5175  if( tmprequiredsize > tmpvarssize )
5176  {
5177  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5178  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5179  tmpvarssize = tmprequiredsize;
5180  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5181  assert( tmprequiredsize <= tmpvarssize );
5182  }
5183 
5184  tmpscalar = 0.0;
5185 
5186  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5187  * possible multi-aggregated variable
5188  */
5189  for( v = ntmpvars - 1; v >= 0; --v )
5190  {
5191  assert(tmpvars[v] != NULL);
5192  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5193 
5194  if( tmpvars[v]->index == var->index )
5195  {
5196  tmpscalar += tmpscalars[v];
5197  tmpvars[v] = tmpvars[ntmpvars - 1];
5198  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5199  --ntmpvars;
5200  }
5201  }
5202 
5203  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5204  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5205  {
5206  if( ntmpvars == 0 )
5207  {
5208  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5209  {
5210  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5211  goto TERMINATE;
5212  }
5213  else /* 0 = c and c != 0 */
5214  {
5215  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5216  *infeasible = TRUE;
5217  goto TERMINATE;
5218  }
5219  }
5220  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5221  {
5222  assert(tmpscalars[0] != 0.0);
5223  assert(tmpvars[0] != NULL);
5224 
5225  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5226  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5227  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5228  goto TERMINATE;
5229  }
5230  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 */
5231  {
5232  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5233 
5234  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5235  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5236 
5237  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5238  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5239  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5240 
5241  goto TERMINATE;
5242  }
5243  else
5244  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5245  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5246  */
5247  goto TERMINATE;
5248  }
5249  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5250  else if( !SCIPsetIsZero(set, tmpscalar) )
5251  {
5252  tmpscalar = 1 - tmpscalar;
5253  tmpconstant /= tmpscalar;
5254  for( v = ntmpvars - 1; v >= 0; --v )
5255  tmpscalars[v] /= tmpscalar;
5256  }
5257 
5258  /* check, if we are in one of the simple cases */
5259  if( ntmpvars == 0 )
5260  {
5261  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5262  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5263  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5264  goto TERMINATE;
5265  }
5266 
5267  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5268  if( ntmpvars == 1 )
5269  {
5270  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5271  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5272 
5273  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5274  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5275  infeasible, aggregated) );
5276 
5277  goto TERMINATE;
5278  }
5279 
5280  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5281  * empty hole list; this should be changed in the future */
5282  if( SCIPvarGetHolelistGlobal(var) != NULL )
5283  goto TERMINATE;
5284 
5285  /* if the variable is not allowed to be multi-aggregated */
5286  if( SCIPvarDoNotMultaggr(var) )
5287  {
5288  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5289  goto TERMINATE;
5290  }
5291 
5292  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5293  * variable bound variable of another variable), we have to remove it from the other variables implications or
5294  * variable bounds
5295  */
5296  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5297  assert(var->vlbs == NULL);
5298  assert(var->vubs == NULL);
5299  assert(var->implics == NULL);
5300  assert(var->cliquelist == NULL);
5301 
5302  /* set the aggregated variable's objective value to 0.0 */
5303  obj = var->obj;
5304  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5305 
5306  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5307  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5308  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5309  * objective of this variable is set to zero
5310  */
5311  SCIPlpDecNLoosevars(lp);
5312 
5313  /* unlock all rounding locks */
5314  nlocksdown = var->nlocksdown;
5315  nlocksup = var->nlocksup;
5316  var->nlocksdown = 0;
5317  var->nlocksup = 0;
5318 
5319  /* convert variable into multi-aggregated variable */
5320  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5321  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5322  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5323  var->data.multaggr.constant = tmpconstant;
5324  var->data.multaggr.nvars = ntmpvars;
5325  var->data.multaggr.varssize = ntmpvars;
5326 
5327  /* mark variable to be non-deletable */
5329 
5330  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variables */
5331  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
5332 
5333  /* update flags and branching factors and priorities of aggregation variables;
5334  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5335  */
5336  branchfactor = var->branchfactor;
5337  branchpriority = var->branchpriority;
5338  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5339 
5340  for( v = 0; v < ntmpvars; ++v )
5341  {
5342  assert(tmpvars[v] != NULL);
5343  tmpvars[v]->removable &= var->removable;
5344  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5345  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5346 
5347  /* mark variable to be non-deletable */
5348  SCIPvarMarkNotDeletable(tmpvars[v]);
5349  }
5350  for( v = 0; v < ntmpvars; ++v )
5351  {
5352  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5353  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5354  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5355  {
5356  if( tmpscalars[v] >= 0.0 )
5357  {
5358  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5359  }
5360  else
5361  {
5362  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5363  }
5364  }
5365  }
5366  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5367  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5368 
5369  if( var->probindex != -1 )
5370  {
5371  /* inform problem about the variable's status change */
5372  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5373  }
5374 
5375  /* issue VARFIXED event */
5376  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5377 
5378  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5379  * variables and the problem's objective offset
5380  */
5381  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5382 
5383  *aggregated = TRUE;
5384 
5385  TERMINATE:
5386  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5387  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5388 
5389  break;
5390 
5391  case SCIP_VARSTATUS_COLUMN:
5392  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5393  return SCIP_INVALIDDATA;
5394 
5395  case SCIP_VARSTATUS_FIXED:
5396  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5397  return SCIP_INVALIDDATA;
5398 
5400  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5401  return SCIP_INVALIDDATA;
5402 
5404  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5405  return SCIP_INVALIDDATA;
5406 
5408  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5409  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5410  */
5411  assert(SCIPsetIsZero(set, var->obj));
5412  assert(var->negatedvar != NULL);
5414  assert(var->negatedvar->negatedvar == var);
5415 
5416  /* switch the signs of the aggregation scalars */
5417  for( v = 0; v < naggvars; ++v )
5418  scalars[v] *= -1.0;
5419 
5420  /* perform the multi aggregation on the negation variable */
5421  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5422  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5423  var->data.negate.constant - constant, infeasible, aggregated) );
5424 
5425  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5426  for( v = 0; v < naggvars; ++v )
5427  scalars[v] *= -1.0;
5428  break;
5429 
5430  default:
5431  SCIPerrorMessage("unknown variable status\n");
5432  return SCIP_INVALIDDATA;
5433  }
5434 
5435  return SCIP_OKAY;
5436 }
5437 
5438 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5439  * or for original variables the same variable is returned
5440  */
5441 static
5443  SCIP_VAR* var /**< problem variable */
5444  )
5445 {
5446  SCIP_VAR* retvar;
5447 
5448  assert(var != NULL);
5449 
5450  retvar = var;
5451 
5452  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5453 
5454  while( TRUE ) /*lint !e716 */
5455  {
5456  assert(retvar != NULL);
5457 
5458  switch( SCIPvarGetStatus(retvar) )
5459  {
5461  case SCIP_VARSTATUS_LOOSE:
5462  case SCIP_VARSTATUS_COLUMN:
5463  case SCIP_VARSTATUS_FIXED:
5464  return retvar;
5465 
5467  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5468  if ( retvar->data.multaggr.nvars == 1 )
5469  retvar = retvar->data.multaggr.vars[0];
5470  else
5471  return retvar;
5472  break;
5473 
5475  retvar = retvar->data.aggregate.var;
5476  break;
5477 
5479  retvar = retvar->negatedvar;
5480  break;
5481 
5482  default:
5483  SCIPerrorMessage("unknown variable status\n");
5484  SCIPABORT();
5485  return NULL; /*lint !e527*/
5486  }
5487  }
5488 }
5489 
5490 /** returns whether variable is not allowed to be multi-aggregated */
5492  SCIP_VAR* var /**< problem variable */
5493  )
5494 {
5495  SCIP_VAR* retvar;
5496 
5497  assert(var != NULL);
5498 
5499  retvar = varGetActiveVar(var);
5500  assert(retvar != NULL);
5501 
5502  switch( SCIPvarGetStatus(retvar) )
5503  {
5505  case SCIP_VARSTATUS_LOOSE:
5506  case SCIP_VARSTATUS_COLUMN:
5507  case SCIP_VARSTATUS_FIXED:
5508  return retvar->donotmultaggr;
5509 
5511  return FALSE;
5512 
5515  default:
5516  SCIPerrorMessage("wrong variable status\n");
5517  SCIPABORT();
5518  return FALSE; /*lint !e527 */
5519  }
5520 }
5521 
5522 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5523  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5524  * negated variable is created
5525  */
5527  SCIP_VAR* var, /**< problem variable to negate */
5528  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5529  SCIP_SET* set, /**< global SCIP settings */
5530  SCIP_STAT* stat, /**< problem statistics */
5531  SCIP_VAR** negvar /**< pointer to store the negated variable */
5532  )
5533 {
5534  assert(var != NULL);
5535  assert(var->scip == set->scip);
5536  assert(negvar != NULL);
5537 
5538  /* check, if we already created the negated variable */
5539  if( var->negatedvar == NULL )
5540  {
5541  char negvarname[SCIP_MAXSTRLEN];
5542 
5543  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5544 
5545  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5546 
5547  /* negation is only possible for bounded variables */
5548  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5549  {
5550  SCIPerrorMessage("cannot negate unbounded variable\n");
5551  return SCIP_INVALIDDATA;
5552  }
5553 
5554  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5555 
5556  /* create negated variable */
5557  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5558  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5559  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5560  if( SCIPvarIsBinary(var) )
5561  (*negvar)->data.negate.constant = 1.0;
5562  else
5563  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5564 
5565  /* create event filter for transformed variable */
5566  if( SCIPvarIsTransformed(var) )
5567  {
5568  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5569  }
5570 
5571  /* set the bounds corresponding to the negation variable */
5572  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5573  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5574  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5575  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5576  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5577 
5578  /* link the variables together */
5579  var->negatedvar = *negvar;
5580  (*negvar)->negatedvar = var;
5581 
5582  /* mark both variables to be non-deletable */
5584  SCIPvarMarkNotDeletable(*negvar);
5585 
5586  /* copy the branch factor and priority, and use the negative preferred branching direction */
5587  (*negvar)->branchfactor = var->branchfactor;
5588  (*negvar)->branchpriority = var->branchpriority;
5589  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5590 
5591  /* copy doNotMultiaggr status */
5592  (*negvar)->donotmultaggr = var->donotmultaggr;
5593 
5594  /* copy lazy bounds (they have to be flipped) */
5595  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5596  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5597 
5598  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5599  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5600  assert((*negvar)->nuses == 1);
5601  }
5602  assert(var->negatedvar != NULL);
5603 
5604  /* return the negated variable */
5605  *negvar = var->negatedvar;
5606 
5607  /* exactly one variable of the negation pair has to be marked as negated variable */
5609 
5610  return SCIP_OKAY;
5611 }
5612 
5613 /** informs variable that its position in problem's vars array changed */
5614 static
5615 void varSetProbindex(
5616  SCIP_VAR* var, /**< problem variable */
5617  int probindex /**< new problem index of variable (-1 for removal) */
5618  )
5619 {
5620  assert(var != NULL);
5621  assert(probindex >= 0 || var->vlbs == NULL);
5622  assert(probindex >= 0 || var->vubs == NULL);
5623  assert(probindex >= 0 || var->implics == NULL);
5624 
5625  var->probindex = probindex;
5627  {
5628  assert(var->data.col != NULL);
5629  var->data.col->var_probindex = probindex;
5630  }
5631 }
5632 
5633 /** informs variable that its position in problem's vars array changed */
5634 void SCIPvarSetProbindex(
5635  SCIP_VAR* var, /**< problem variable */
5636  int probindex /**< new problem index of variable */
5637  )
5638 {
5639  assert(var != NULL);
5640  assert(probindex >= 0);
5641 
5642  varSetProbindex(var, probindex);
5643 }
5644 
5645 /** gives the variable a new name
5646  *
5647  * @note the old pointer is overwritten, which might result in a memory leakage
5648  */
5650  SCIP_VAR* var, /**< problem variable */
5651  const char* name /**< new name of variable */
5652  )
5653 {
5654  assert(var != NULL);
5655  assert(name != NULL);
5656 
5657  var->name = (char*)name;
5658 }
5659 
5660 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5661  * implication graph;
5662  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5663  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5664  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5665  * than removing the variables one by one, each time updating all lists of the other variables.
5666  */
5668  SCIP_VAR* var, /**< problem variable */
5669  BMS_BLKMEM* blkmem, /**< block memory buffer */
5670  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5671  SCIP_SET* set, /**< global SCIP settings */
5672  SCIP_Bool final /**< is this the final removal of all problem variables? */
5673  )
5674 {
5675  assert(SCIPvarGetProbindex(var) >= 0);
5676  assert(var->scip == set->scip);
5677 
5678  /* if the variable is active in the transformed problem, remove it from the implication graph */
5679  if( SCIPvarIsTransformed(var)
5681  {
5682  if( final )
5683  {
5684  /* just destroy the data structures */
5685  SCIPvboundsFree(&var->vlbs, blkmem);
5686  SCIPvboundsFree(&var->vubs, blkmem);
5687  SCIPimplicsFree(&var->implics, blkmem);
5688  }
5689  else
5690  {
5691  /* unlink the variable from all other variables' lists and free the data structures */
5692  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5693  }
5694  }
5695 
5696  /* mark the variable to be no longer a member of the problem */
5697  varSetProbindex(var, -1);
5698 
5699  return SCIP_OKAY;
5700 }
5701 
5702 /** marks the variable to be deleted from the problem */
5703 void SCIPvarMarkDeleted(
5704  SCIP_VAR* var /**< problem variable */
5705  )
5706 {
5707  assert(var != NULL);
5708  assert(var->probindex != -1);
5709 
5710  var->deleted = TRUE;
5711 }
5712 
5713 /** marks the variable to not to be multi-aggregated */
5715  SCIP_VAR* var /**< problem variable */
5716  )
5717 {
5718  SCIP_VAR* retvar;
5719 
5720  assert(var != NULL);
5721 
5722  retvar = varGetActiveVar(var);
5723  assert(retvar != NULL);
5724 
5725  switch( SCIPvarGetStatus(retvar) )
5726  {
5728  case SCIP_VARSTATUS_LOOSE:
5729  case SCIP_VARSTATUS_COLUMN:
5730  case SCIP_VARSTATUS_FIXED:
5731  retvar->donotmultaggr = TRUE;
5732  break;
5733 
5735  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5736  return SCIP_INVALIDDATA;
5737 
5740  default:
5741  SCIPerrorMessage("wrong variable status\n");
5742  return SCIP_INVALIDDATA;
5743  }
5744 
5745  return SCIP_OKAY;
5746 }
5747 
5748 /** changes type of variable; cannot be called, if var belongs to a problem */
5750  SCIP_VAR* var, /**< problem variable to change */
5751  SCIP_VARTYPE vartype /**< new type of variable */
5752  )
5753 {
5754  assert(var != NULL);
5755 
5756  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5757 
5758  if( var->probindex >= 0 )
5759  {
5760  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5761  return SCIP_INVALIDDATA;
5762  }
5763 
5764  var->vartype = vartype; /*lint !e641*/
5765  if( var->negatedvar != NULL )
5766  var->negatedvar->vartype = vartype; /*lint !e641*/
5767 
5768  return SCIP_OKAY;
5769 }
5770 
5771 /** appends OBJCHANGED event to the event queue */
5772 static
5774  SCIP_VAR* var, /**< problem variable to change */
5775  BMS_BLKMEM* blkmem, /**< block memory */
5776  SCIP_SET* set, /**< global SCIP settings */
5777  SCIP_PRIMAL* primal, /**< primal data */
5778  SCIP_LP* lp, /**< current LP data */
5779  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5780  SCIP_Real oldobj, /**< old objective value for variable */
5781  SCIP_Real newobj /**< new objective value for variable */
5782  )
5783 {
5784  SCIP_EVENT* event;
5785 
5786  assert(var != NULL);
5787  assert(var->scip == set->scip);
5788  assert(var->eventfilter != NULL);
5790  assert(SCIPvarIsTransformed(var));
5791  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5792 
5793  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5794  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5795 
5796  return SCIP_OKAY;
5797 }
5798 
5799 /** changes objective value of variable */
5801  SCIP_VAR* var, /**< variable to change */
5802  BMS_BLKMEM* blkmem, /**< block memory */
5803  SCIP_SET* set, /**< global SCIP settings */
5804  SCIP_PROB* prob, /**< problem data */
5805  SCIP_PRIMAL* primal, /**< primal data */
5806  SCIP_LP* lp, /**< current LP data */
5807  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5808  SCIP_Real newobj /**< new objective value for variable */
5809  )
5810 {
5811  SCIP_Real oldobj;
5812 
5813  assert(var != NULL);
5814  assert(set != NULL);
5815  assert(var->scip == set->scip);
5816 
5817  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5818 
5819  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5820  {
5821  switch( SCIPvarGetStatus(var) )
5822  {
5824  if( var->data.original.transvar != NULL )
5825  {
5826  assert(SCIPprobIsTransformed(prob));
5827 
5828  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
5829  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
5830  }
5831  else
5832  assert(set->stage == SCIP_STAGE_PROBLEM);
5833 
5834  var->obj = newobj;
5835  var->unchangedobj = newobj;
5836 
5837  break;
5838 
5839  case SCIP_VARSTATUS_LOOSE:
5840  case SCIP_VARSTATUS_COLUMN:
5841  oldobj = var->obj;
5842  var->obj = newobj;
5843 
5844  /* update unchanged objective value of variable */
5845  if( !lp->divingobjchg )
5846  var->unchangedobj = newobj;
5847 
5848  /* update the number of variables with non-zero objective coefficient;
5849  * we only want to do the update, if the variable is added to the problem;
5850  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5851  */
5852  if( SCIPvarIsActive(var) )
5853  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
5854 
5855  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5856  break;
5857 
5858  case SCIP_VARSTATUS_FIXED:
5862  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
5863  return SCIP_INVALIDDATA;
5864 
5865  default:
5866  SCIPerrorMessage("unknown variable status\n");
5867  return SCIP_INVALIDDATA;
5868  }
5869  }
5870 
5871  return SCIP_OKAY;
5872 }
5873 
5874 /** adds value to objective value of variable */
5876  SCIP_VAR* var, /**< variable to change */
5877  BMS_BLKMEM* blkmem, /**< block memory */
5878  SCIP_SET* set, /**< global SCIP settings */
5879  SCIP_STAT* stat, /**< problem statistics */
5880  SCIP_PROB* transprob, /**< transformed problem data */
5881  SCIP_PROB* origprob, /**< original problem data */
5882  SCIP_PRIMAL* primal, /**< primal data */
5883  SCIP_TREE* tree, /**< branch and bound tree */
5884  SCIP_REOPT* reopt, /**< reoptimization data structure */
5885  SCIP_LP* lp, /**< current LP data */
5886  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5887  SCIP_Real addobj /**< additional objective value for variable */
5888  )
5889 {
5890  assert(var != NULL);
5891  assert(set != NULL);
5892  assert(var->scip == set->scip);
5893  assert(set->stage < SCIP_STAGE_INITSOLVE);
5894 
5895  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
5896 
5897  if( !SCIPsetIsZero(set, addobj) )
5898  {
5899  SCIP_Real oldobj;
5900  int i;
5901 
5902  switch( SCIPvarGetStatus(var) )
5903  {
5905  if( var->data.original.transvar != NULL )
5906  {
5907  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5908  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
5909  }
5910  else
5911  assert(set->stage == SCIP_STAGE_PROBLEM);
5912 
5913  var->obj += addobj;
5914  var->unchangedobj += addobj;
5915  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5916 
5917  break;
5918 
5919  case SCIP_VARSTATUS_LOOSE:
5920  case SCIP_VARSTATUS_COLUMN:
5921  oldobj = var->obj;
5922  var->obj += addobj;
5923 
5924  /* update unchanged objective value of variable */
5925  if( !lp->divingobjchg )
5926  {
5927  var->unchangedobj += addobj;
5928  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
5929  }
5930 
5931  /* update the number of variables with non-zero objective coefficient;
5932  * we only want to do the update, if the variable is added to the problem;
5933  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5934  */
5935  if( SCIPvarIsActive(var) )
5936  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
5937 
5938  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5939  break;
5940 
5941  case SCIP_VARSTATUS_FIXED:
5942  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
5943  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
5944  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5945  break;
5946 
5948  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
5949  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
5950  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5951  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
5952  lp, eventqueue, var->data.aggregate.scalar * addobj) );
5953  break;
5954 
5956  assert(!var->donotmultaggr);
5957  /* 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 */
5958  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
5959  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5960  for( i = 0; i < var->data.multaggr.nvars; ++i )
5961  {
5962  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
5963  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
5964  }
5965  break;
5966 
5968  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
5969  assert(var->negatedvar != NULL);
5971  assert(var->negatedvar->negatedvar == var);
5972  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
5973  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
5974  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5975  eventqueue, -addobj) );
5976  break;
5977 
5978  default:
5979  SCIPerrorMessage("unknown variable status\n");
5980  return SCIP_INVALIDDATA;
5981  }
5982  }
5983 
5984  return SCIP_OKAY;
5985 }
5986 
5987 /** changes objective value of variable in current dive */
5989  SCIP_VAR* var, /**< problem variable to change */
5990  SCIP_SET* set, /**< global SCIP settings */
5991  SCIP_LP* lp, /**< current LP data */
5992  SCIP_Real newobj /**< new objective value for variable */
5993  )
5994 {
5995  assert(var != NULL);
5996  assert(set != NULL);
5997  assert(var->scip == set->scip);
5998  assert(lp != NULL);
5999 
6000  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6001 
6002  if( SCIPsetIsZero(set, newobj) )
6003  newobj = 0.0;
6004 
6005  /* change objective value of attached variables */
6006  switch( SCIPvarGetStatus(var) )
6007  {
6009  assert(var->data.original.transvar != NULL);
6010  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6011  break;
6012 
6013  case SCIP_VARSTATUS_COLUMN:
6014  assert(var->data.col != NULL);
6015  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6016  break;
6017 
6018  case SCIP_VARSTATUS_LOOSE:
6019  case SCIP_VARSTATUS_FIXED:
6020  /* nothing to do here: only the constant shift in objective function would change */
6021  break;
6022 
6023  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6024  assert(var->data.aggregate.var != NULL);
6025  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6026  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6027  /* the constant can be ignored, because it would only affect the objective shift */
6028  break;
6029 
6031  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6032  return SCIP_INVALIDDATA;
6033 
6034  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6035  assert(var->negatedvar != NULL);
6037  assert(var->negatedvar->negatedvar == var);
6038  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6039  /* the offset can be ignored, because it would only affect the objective shift */
6040  break;
6041 
6042  default:
6043  SCIPerrorMessage("unknown variable status\n");
6044  return SCIP_INVALIDDATA;
6045  }
6046 
6047  return SCIP_OKAY;
6048 }
6049 
6050 /** adjust lower bound to integral value, if variable is integral */
6051 void SCIPvarAdjustLb(
6052  SCIP_VAR* var, /**< problem variable */
6053  SCIP_SET* set, /**< global SCIP settings */
6054  SCIP_Real* lb /**< pointer to lower bound to adjust */
6055  )
6056 {
6057  assert(var != NULL);
6058  assert(set != NULL);
6059  assert(var->scip == set->scip);
6060  assert(lb != NULL);
6061 
6062  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6063 
6064  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6065 }
6066 
6067 /** adjust upper bound to integral value, if variable is integral */
6068 void SCIPvarAdjustUb(
6069  SCIP_VAR* var, /**< problem variable */
6070  SCIP_SET* set, /**< global SCIP settings */
6071  SCIP_Real* ub /**< pointer to upper bound to adjust */
6072  )
6073 {
6074  assert(var != NULL);
6075  assert(set != NULL);
6076  assert(var->scip == set->scip);
6077  assert(ub != NULL);
6078 
6079  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6080 
6081  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6082 }
6083 
6084 /** adjust lower or upper bound to integral value, if variable is integral */
6085 void SCIPvarAdjustBd(
6086  SCIP_VAR* var, /**< problem variable */
6087  SCIP_SET* set, /**< global SCIP settings */
6088  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6089  SCIP_Real* bd /**< pointer to bound to adjust */
6090  )
6091 {
6092  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6093 
6094  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6095  SCIPvarAdjustLb(var, set, bd);
6096  else
6097  SCIPvarAdjustUb(var, set, bd);
6098 }
6099 
6100 /** changes lower bound of original variable in original problem */
6102  SCIP_VAR* var, /**< problem variable to change */
6103  SCIP_SET* set, /**< global SCIP settings */
6104  SCIP_Real newbound /**< new bound for variable */
6105  )
6106 {
6107  int i;
6108 
6109  assert(var != NULL);
6110  assert(!SCIPvarIsTransformed(var));
6112  assert(set != NULL);
6113  assert(var->scip == set->scip);
6114  assert(set->stage == SCIP_STAGE_PROBLEM);
6115 
6116  /* check that the bound is feasible */
6117  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6118  /* adjust bound to integral value if variable is of integral type */
6119  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6120 
6121  if( SCIPsetIsZero(set, newbound) )
6122  newbound = 0.0;
6123 
6124  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6126  {
6127  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6128  var->name, var->data.original.origdom.lb, newbound);
6129 
6130  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6131  return SCIP_OKAY;
6132 
6133  /* change the bound */
6134  var->data.original.origdom.lb = newbound;
6135  }
6136  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6137  {
6138  assert( var->negatedvar != NULL );
6139  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6140  }
6141 
6142  /* process parent variables */
6143  for( i = 0; i < var->nparentvars; ++i )
6144  {
6145  SCIP_VAR* parentvar;
6146 
6147  parentvar = var->parentvars[i];
6148  assert(parentvar != NULL);
6149  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6150  assert(parentvar->negatedvar == var);
6151  assert(var->negatedvar == parentvar);
6152 
6153  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6154  }
6155 
6156  return SCIP_OKAY;
6157 }
6158 
6159 /** changes upper bound of original variable in original problem */
6161  SCIP_VAR* var, /**< problem variable to change */
6162  SCIP_SET* set, /**< global SCIP settings */
6163  SCIP_Real newbound /**< new bound for variable */
6164  )
6165 {
6166  int i;
6167 
6168  assert(var != NULL);
6169  assert(!SCIPvarIsTransformed(var));
6171  assert(set != NULL);
6172  assert(var->scip == set->scip);
6173  assert(set->stage == SCIP_STAGE_PROBLEM);
6174 
6175  /* check that the bound is feasible */
6176  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6177  /* adjust bound to integral value if variable is of integral type */
6178  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6179 
6180  if( SCIPsetIsZero(set, newbound) )
6181  newbound = 0.0;
6182 
6183  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6185  {
6186  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6187  var->name, var->data.original.origdom.ub, newbound);
6188 
6189  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6190  return SCIP_OKAY;
6191 
6192  /* change the bound */
6193  var->data.original.origdom.ub = newbound;
6194  }
6195  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6196  {
6197  assert( var->negatedvar != NULL );
6198  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6199  }
6200 
6201  /* process parent variables */
6202  for( i = 0; i < var->nparentvars; ++i )
6203  {
6204  SCIP_VAR* parentvar;
6205 
6206  parentvar = var->parentvars[i];
6207  assert(parentvar != NULL);
6208  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6209  assert(parentvar->negatedvar == var);
6210  assert(var->negatedvar == parentvar);
6211 
6212  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6213  }
6214 
6215  return SCIP_OKAY;
6216 }
6217 
6218 /** appends GLBCHANGED event to the event queue */
6219 static
6221  SCIP_VAR* var, /**< problem variable to change */
6222  BMS_BLKMEM* blkmem, /**< block memory */
6223  SCIP_SET* set, /**< global SCIP settings */
6224  SCIP_LP* lp, /**< current LP data */
6225  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6226  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6227  SCIP_Real oldbound, /**< old lower bound for variable */
6228  SCIP_Real newbound /**< new lower bound for variable */
6229  )
6230 {
6231  assert(var != NULL);
6232  assert(var->eventfilter != NULL);
6233  assert(SCIPvarIsTransformed(var));
6234  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6235  assert(set != NULL);
6236  assert(var->scip == set->scip);
6237 
6238  /* check, if the variable is being tracked for bound changes
6239  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6240  */
6241  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6244  {
6245  SCIP_EVENT* event;
6246 
6247  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6248 
6249  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6250  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6251  }
6252 
6253  return SCIP_OKAY;
6254 }
6255 
6256 /** appends GUBCHANGED event to the event queue */
6257 static
6259  SCIP_VAR* var, /**< problem variable to change */
6260  BMS_BLKMEM* blkmem, /**< block memory */
6261  SCIP_SET* set, /**< global SCIP settings */
6262  SCIP_LP* lp, /**< current LP data */
6263  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6264  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6265  SCIP_Real oldbound, /**< old lower bound for variable */
6266  SCIP_Real newbound /**< new lower bound for variable */
6267  )
6268 {
6269  assert(var != NULL);
6270  assert(var->eventfilter != NULL);
6271  assert(SCIPvarIsTransformed(var));
6272  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6273  assert(set != NULL);
6274  assert(var->scip == set->scip);
6275 
6276  /* check, if the variable is being tracked for bound changes
6277  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6278  */
6279  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6282  {
6283  SCIP_EVENT* event;
6284 
6285  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6286 
6287  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6288  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6289  }
6290 
6291  return SCIP_OKAY;
6292 }
6293 
6294 /** appends GHOLEADDED event to the event queue */
6295 static
6297  SCIP_VAR* var, /**< problem variable to change */
6298  BMS_BLKMEM* blkmem, /**< block memory */
6299  SCIP_SET* set, /**< global SCIP settings */
6300  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6301  SCIP_Real left, /**< left bound of open interval in new hole */
6302  SCIP_Real right /**< right bound of open interval in new hole */
6303  )
6304 {
6305  assert(var != NULL);
6306  assert(var->eventfilter != NULL);
6307  assert(SCIPvarIsTransformed(var));
6308  assert(set != NULL);
6309  assert(var->scip == set->scip);
6310  assert(SCIPsetIsLT(set, left, right));
6311 
6312  /* check, if the variable is being tracked for bound changes */
6313  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6314  {
6315  SCIP_EVENT* event;
6316 
6317  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6318 
6319  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6320  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6321  }
6322 
6323  return SCIP_OKAY;
6324 }
6325 
6326 /** increases root bound change statistics after a global bound change */
6327 static
6328 void varIncRootboundchgs(
6329  SCIP_VAR* var, /**< problem variable to change */
6330  SCIP_SET* set, /**< global SCIP settings */
6331  SCIP_STAT* stat /**< problem statistics */
6332  )
6333 {
6334  assert(var != NULL);
6335  assert(set != NULL);
6336  assert(var->scip == set->scip);
6337  assert(stat != NULL);
6338 
6339  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6340  {
6341  stat->nrootboundchgs++;
6342  stat->nrootboundchgsrun++;
6343  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6344  {
6345  stat->nrootintfixings++;
6346  stat->nrootintfixingsrun++;
6347  }
6348  }
6349 }
6350 
6351 /* forward declaration, because both methods call each other recursively */
6352 
6353 /* performs the current change in upper bound, changes all parents accordingly */
6354 static
6356  SCIP_VAR* var, /**< problem variable to change */
6357  BMS_BLKMEM* blkmem, /**< block memory */
6358  SCIP_SET* set, /**< global SCIP settings */
6359  SCIP_STAT* stat, /**< problem statistics */
6360  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6361  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6362  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6363  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6364  SCIP_Real newbound /**< new bound for variable */
6365  );
6366 
6367 /** performs the current change in lower bound, changes all parents accordingly */
6368 static
6370  SCIP_VAR* var, /**< problem variable to change */
6371  BMS_BLKMEM* blkmem, /**< block memory */
6372  SCIP_SET* set, /**< global SCIP settings */
6373  SCIP_STAT* stat, /**< problem statistics */
6374  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6375  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6376  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6377  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6378  SCIP_Real newbound /**< new bound for variable */
6379  )
6380 {
6381  SCIP_VAR* parentvar;
6382  SCIP_Real oldbound;
6383  int i;
6384 
6385  assert(var != NULL);
6386  /* local domains can violate global bounds but not more than feasibility epsilon */
6387  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6388  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6389  assert(blkmem != NULL);
6390  assert(set != NULL);
6391  assert(var->scip == set->scip);
6392  assert(stat != NULL);
6393 
6394  /* adjust bound to integral value if variable is of integral type */
6395  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6396 
6397  /* check that the bound is feasible */
6398  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6399  {
6400  /* due to numerics we only want to be feasible in feasibility tolerance */
6401  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6402  newbound = var->glbdom.ub;
6403  }
6404  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6405 
6406  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6407 
6408  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6409 
6410  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6411  return SCIP_OKAY;
6412 
6413  /* check bound on debugging solution */
6414  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6415 
6416  /* change the bound */
6417  oldbound = var->glbdom.lb;
6418  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6419  var->glbdom.lb = newbound;
6420  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6421  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6422 
6423  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6424  {
6425  /* merges overlapping holes into single holes, moves bounds respectively */
6426  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6427  }
6428 
6429  /* update the root bound changes counters */
6430  varIncRootboundchgs(var, set, stat);
6431 
6432  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6433  * redundant bound changes to be branching decisions
6434  */
6435  for( i = 0; i < var->nlbchginfos; ++i )
6436  {
6437  assert(var->lbchginfos[i].var == var);
6438 
6439  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6440  {
6441  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6442  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6443  var->lbchginfos[i].oldbound = var->glbdom.lb;
6444  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6445  {
6446  /* this bound change is redundant due to the new global bound */
6447  var->lbchginfos[i].newbound = var->glbdom.lb;
6448  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6449  var->lbchginfos[i].redundant = TRUE;
6450  }
6451  else
6452  break; /* from now on, the remaining local bound changes are not redundant */
6453  }
6454  else
6455  break; /* from now on, the remaining local bound changes are not redundant */
6456  }
6457 
6458  /* remove redundant implications and variable bounds */
6460  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6461  {
6462  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6463  }
6464 
6465  /* issue bound change event */
6466  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6467  if( var->eventfilter != NULL )
6468  {
6469  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6470  }
6471 
6472  /* process parent variables */
6473  for( i = 0; i < var->nparentvars; ++i )
6474  {
6475  parentvar = var->parentvars[i];
6476  assert(parentvar != NULL);
6477 
6478  switch( SCIPvarGetStatus(parentvar) )
6479  {
6481  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6482  break;
6483 
6484  case SCIP_VARSTATUS_COLUMN:
6485  case SCIP_VARSTATUS_LOOSE:
6486  case SCIP_VARSTATUS_FIXED:
6488  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6489  return SCIP_INVALIDDATA;
6490 
6491  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6492  assert(parentvar->data.aggregate.var == var);
6493  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6494  {
6495  SCIP_Real parentnewbound;
6496 
6497  /* a > 0 -> change lower bound of y */
6498  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, -oldbound))
6499  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6500  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6501 
6502  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6503  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6504  else
6505  parentnewbound = newbound;
6506  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6507  }
6508  else
6509  {
6510  SCIP_Real parentnewbound;
6511 
6512  /* a < 0 -> change upper bound of y */
6513  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6514  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, -oldbound))
6515  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6516  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6517 
6518  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6519  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6520  else
6521  parentnewbound = -newbound;
6522  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6523  }
6524  break;
6525 
6526  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6527  assert(parentvar->negatedvar != NULL);
6528  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6529  assert(parentvar->negatedvar->negatedvar == parentvar);
6530  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6531  parentvar->data.negate.constant - newbound) );
6532  break;
6533 
6534  default:
6535  SCIPerrorMessage("unknown variable status\n");
6536  return SCIP_INVALIDDATA;
6537  }
6538  }
6539 
6540  return SCIP_OKAY;
6541 }
6542 
6543 /** performs the current change in upper bound, changes all parents accordingly */
6544 static
6546  SCIP_VAR* var, /**< problem variable to change */
6547  BMS_BLKMEM* blkmem, /**< block memory */
6548  SCIP_SET* set, /**< global SCIP settings */
6549  SCIP_STAT* stat, /**< problem statistics */
6550  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6551  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6552  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6553  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6554  SCIP_Real newbound /**< new bound for variable */
6555  )
6556 {
6557  SCIP_VAR* parentvar;
6558  SCIP_Real oldbound;
6559  int i;
6560 
6561  assert(var != NULL);
6562  /* local domains can violate global bounds but not more than feasibility epsilon */
6563  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6564  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6565  assert(blkmem != NULL);
6566  assert(set != NULL);
6567  assert(var->scip == set->scip);
6568  assert(stat != NULL);
6569 
6570  /* adjust bound to integral value if variable is of integral type */
6571  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6572 
6573  /* check that the bound is feasible */
6574  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6575  {
6576  /* due to numerics we only want to be feasible in feasibility tolerance */
6577  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6578  newbound = var->glbdom.lb;
6579  }
6580  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6581 
6582  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6583 
6584  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6585 
6586  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6587  return SCIP_OKAY;
6588 
6589  /* check bound on debugging solution */
6590  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6591 
6592  /* change the bound */
6593  oldbound = var->glbdom.ub;
6594  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6595  var->glbdom.ub = newbound;
6596  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6597  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6598 
6599  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6600  {
6601  /* merges overlapping holes into single holes, moves bounds respectively */
6602  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6603  }
6604 
6605  /* update the root bound changes counters */
6606  varIncRootboundchgs(var, set, stat);
6607 
6608  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6609  * redundant bound changes to be branching decisions
6610  */
6611  for( i = 0; i < var->nubchginfos; ++i )
6612  {
6613  assert(var->ubchginfos[i].var == var);
6614  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6615  {
6616  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6617  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6618  var->ubchginfos[i].oldbound = var->glbdom.ub;
6619  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6620  {
6621  /* this bound change is redundant due to the new global bound */
6622  var->ubchginfos[i].newbound = var->glbdom.ub;
6623  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6624  var->ubchginfos[i].redundant = TRUE;
6625  }
6626  else
6627  break; /* from now on, the remaining local bound changes are not redundant */
6628  }
6629  else
6630  break; /* from now on, the remaining local bound changes are not redundant */
6631  }
6632 
6633  /* remove redundant implications and variable bounds */
6635  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6636  {
6637  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6638  }
6639 
6640  /* issue bound change event */
6641  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6642  if( var->eventfilter != NULL )
6643  {
6644  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6645  }
6646 
6647  /* process parent variables */
6648  for( i = 0; i < var->nparentvars; ++i )
6649  {
6650  parentvar = var->parentvars[i];
6651  assert(parentvar != NULL);
6652 
6653  switch( SCIPvarGetStatus(parentvar) )
6654  {
6656  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6657  break;
6658 
6659  case SCIP_VARSTATUS_COLUMN:
6660  case SCIP_VARSTATUS_LOOSE:
6661  case SCIP_VARSTATUS_FIXED:
6663  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6664  return SCIP_INVALIDDATA;
6665 
6666  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6667  assert(parentvar->data.aggregate.var == var);
6668  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6669  {
6670  SCIP_Real parentnewbound;
6671 
6672  /* a > 0 -> change upper bound of y */
6673  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, oldbound))
6674  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6675  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6676  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6677  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6678  else
6679  parentnewbound = newbound;
6680  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6681  }
6682  else
6683  {
6684  SCIP_Real parentnewbound;
6685 
6686  /* a < 0 -> change lower bound of y */
6687  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6688  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, oldbound))
6689  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6690  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6691  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6692  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6693  else
6694  parentnewbound = -newbound;
6695  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6696  }
6697  break;
6698 
6699  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6700  assert(parentvar->negatedvar != NULL);
6701  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6702  assert(parentvar->negatedvar->negatedvar == parentvar);
6703  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6704  parentvar->data.negate.constant - newbound) );
6705  break;
6706 
6707  default:
6708  SCIPerrorMessage("unknown variable status\n");
6709  return SCIP_INVALIDDATA;
6710  }
6711  }
6712 
6713  return SCIP_OKAY;
6714 }
6715 
6716 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6717  * updates local lower bound if the global bound is tighter
6718  */
6720  SCIP_VAR* var, /**< problem variable to change */
6721  BMS_BLKMEM* blkmem, /**< block memory */
6722  SCIP_SET* set, /**< global SCIP settings */
6723  SCIP_STAT* stat, /**< problem statistics */
6724  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6725  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6726  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6727  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6728  SCIP_Real newbound /**< new bound for variable */
6729  )
6730 {
6731  assert(var != NULL);
6732  assert(blkmem != NULL);
6733  assert(set != NULL);
6734  assert(var->scip == set->scip);
6735 
6736  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6737  * of the domain within feastol
6738  */
6739  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6740 
6741  /* adjust bound to integral value if variable is of integral type */
6742  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6743 
6744  /* check that the adjusted bound is feasible
6745  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6746  * here because we reset bounds to their original value!
6747  */
6748  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6749 
6750  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6751  {
6752  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6753  newbound = MIN(newbound, var->glbdom.ub);
6754  }
6755  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6756 
6757  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6758  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6759  */
6760  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6761 
6762  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6763 
6764  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6765  return SCIP_OKAY;
6766 
6767  /* change bounds of attached variables */
6768  switch( SCIPvarGetStatus(var) )
6769  {
6771  if( var->data.original.transvar != NULL )
6772  {
6773  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6774  cliquetable, newbound) );
6775  }
6776  else
6777  {
6778  assert(set->stage == SCIP_STAGE_PROBLEM);
6779  if( newbound > SCIPvarGetLbLocal(var) )
6780  {
6781  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6782  }
6783  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6784  }
6785  break;
6786 
6787  case SCIP_VARSTATUS_COLUMN:
6788  case SCIP_VARSTATUS_LOOSE:
6789  if( newbound > SCIPvarGetLbLocal(var) )
6790  {
6791  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6792  }
6793  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6794  break;
6795 
6796  case SCIP_VARSTATUS_FIXED:
6797  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6798  return SCIP_INVALIDDATA;
6799 
6800  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6801  assert(var->data.aggregate.var != NULL);
6802  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6803  {
6804  SCIP_Real childnewbound;
6805 
6806  /* a > 0 -> change lower bound of y */
6807  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6808  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6810  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6811  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6812  else
6813  childnewbound = newbound;
6814  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6815  childnewbound) );
6816  }
6817  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6818  {
6819  SCIP_Real childnewbound;
6820 
6821  /* a < 0 -> change upper bound of y */
6822  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6823  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6825  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6826  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6827  else
6828  childnewbound = -newbound;
6829  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6830  childnewbound) );
6831  }
6832  else
6833  {
6834  SCIPerrorMessage("scalar is zero in aggregation\n");
6835  return SCIP_INVALIDDATA;
6836  }
6837  break;
6838 
6840  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6841  return SCIP_INVALIDDATA;
6842 
6843  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6844  assert(var->negatedvar != NULL);
6846  assert(var->negatedvar->negatedvar == var);
6847  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6848  var->data.negate.constant - newbound) );
6849  break;
6850 
6851  default:
6852  SCIPerrorMessage("unknown variable status\n");
6853  return SCIP_INVALIDDATA;
6854  }
6855 
6856  return SCIP_OKAY;
6857 }
6858 
6859 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
6860  * updates local upper bound if the global bound is tighter
6861  */
6863  SCIP_VAR* var, /**< problem variable to change */
6864  BMS_BLKMEM* blkmem, /**< block memory */
6865  SCIP_SET* set, /**< global SCIP settings */
6866  SCIP_STAT* stat, /**< problem statistics */
6867  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6868  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6869  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6870  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6871  SCIP_Real newbound /**< new bound for variable */
6872  )
6873 {
6874  assert(var != NULL);
6875  assert(blkmem != NULL);
6876  assert(set != NULL);
6877  assert(var->scip == set->scip);
6878 
6879  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6880  * of the domain within feastol
6881  */
6882  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6883 
6884  /* adjust bound to integral value if variable is of integral type */
6885  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6886 
6887  /* check that the adjusted bound is feasible
6888  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6889  * here because we reset bounds to their original value!
6890  */
6891  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6892 
6893  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6894  {
6895  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
6896  newbound = MAX(newbound, var->glbdom.lb);
6897  }
6898  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6899 
6900  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6901  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6902  */
6903  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6904 
6905  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
6906 
6907  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
6908  return SCIP_OKAY;
6909 
6910  /* change bounds of attached variables */
6911  switch( SCIPvarGetStatus(var) )
6912  {
6914  if( var->data.original.transvar != NULL )
6915  {
6916  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6917  newbound) );
6918  }
6919  else
6920  {
6921  assert(set->stage == SCIP_STAGE_PROBLEM);
6922  if( newbound < SCIPvarGetUbLocal(var) )
6923  {
6924  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6925  }
6926  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6927  }
6928  break;
6929 
6930  case SCIP_VARSTATUS_COLUMN:
6931  case SCIP_VARSTATUS_LOOSE:
6932  if( newbound < SCIPvarGetUbLocal(var) )
6933  {
6934  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6935  }
6936  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6937  break;
6938 
6939  case SCIP_VARSTATUS_FIXED:
6940  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6941  return SCIP_INVALIDDATA;
6942 
6943  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6944  assert(var->data.aggregate.var != NULL);
6945  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6946  {
6947  SCIP_Real childnewbound;
6948 
6949  /* a > 0 -> change lower bound of y */
6950  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6951  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6953  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6954  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6955  else
6956  childnewbound = newbound;
6957  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6958  childnewbound) );
6959  }
6960  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6961  {
6962  SCIP_Real childnewbound;
6963 
6964  /* a < 0 -> change upper bound of y */
6965  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6966  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
6968  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6969  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6970  else
6971  childnewbound = -newbound;
6972  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6973  childnewbound) );
6974  }
6975  else
6976  {
6977  SCIPerrorMessage("scalar is zero in aggregation\n");
6978  return SCIP_INVALIDDATA;
6979  }
6980  break;
6981 
6983  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6984  return SCIP_INVALIDDATA;
6985 
6986  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6987  assert(var->negatedvar != NULL);
6989  assert(var->negatedvar->negatedvar == var);
6990  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6991  var->data.negate.constant - newbound) );
6992  break;
6993 
6994  default:
6995  SCIPerrorMessage("unknown variable status\n");
6996  return SCIP_INVALIDDATA;
6997  }
6998 
6999  return SCIP_OKAY;
7000 }
7001 
7002 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7004  SCIP_VAR* var, /**< problem variable */
7005  SCIP_SET* set, /**< global SCIP settings */
7006  SCIP_Real lazylb /**< the lazy lower bound to be set */
7007  )
7008 {
7009  assert(var != NULL);
7010  assert(var->probindex != -1);
7011  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7012  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7013  assert(set != NULL);
7014  assert(var->scip == set->scip);
7015 
7016  /* variable should not be in the LP */
7018  return SCIP_INVALIDCALL;
7019 
7020  var->lazylb = lazylb;
7021 
7022  return SCIP_OKAY;
7023 }
7024 
7025 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7027  SCIP_VAR* var, /**< problem variable */
7028  SCIP_SET* set, /**< global SCIP settings */
7029  SCIP_Real lazyub /**< the lazy lower bound to be set */
7030  )
7031 {
7032  assert(var != NULL);
7033  assert(var->probindex != -1);
7034  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7035  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7036  assert(set != NULL);
7037  assert(var->scip == set->scip);
7038 
7039  /* variable should not be in the LP */
7041  return SCIP_INVALIDCALL;
7042 
7043  var->lazyub = lazyub;
7044 
7045  return SCIP_OKAY;
7046 }
7047 
7048 
7049 /** changes global bound of variable; if possible, adjusts bound to integral value;
7050  * updates local bound if the global bound is tighter
7051  */
7053  SCIP_VAR* var, /**< problem variable to change */
7054  BMS_BLKMEM* blkmem, /**< block memory */
7055  SCIP_SET* set, /**< global SCIP settings */
7056  SCIP_STAT* stat, /**< problem statistics */
7057  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7058  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7059  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7060  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7061  SCIP_Real newbound, /**< new bound for variable */
7062  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7063  )
7064 {
7065  /* apply bound change to the LP data */
7066  switch( boundtype )
7067  {
7068  case SCIP_BOUNDTYPE_LOWER:
7069  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7070  case SCIP_BOUNDTYPE_UPPER:
7071  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7072  default:
7073  SCIPerrorMessage("unknown bound type\n");
7074  return SCIP_INVALIDDATA;
7075  }
7076 }
7077 
7078 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7079 static
7081  SCIP_VAR* var, /**< problem variable to change */
7082  BMS_BLKMEM* blkmem, /**< block memory */
7083  SCIP_SET* set, /**< global SCIP settings */
7084  SCIP_LP* lp, /**< current LP data */
7085  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7086  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7087  SCIP_Real oldbound, /**< old lower bound for variable */
7088  SCIP_Real newbound /**< new lower bound for variable */
7089  )
7090 {
7091  assert(var != NULL);
7092  assert(var->eventfilter != NULL);
7093  assert(SCIPvarIsTransformed(var));
7094  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7095  assert(set != NULL);
7096  assert(var->scip == set->scip);
7097 
7098  /* check, if the variable is being tracked for bound changes
7099  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7100  */
7101  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7104  {
7105  SCIP_EVENT* event;
7106 
7107  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7108 
7109  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7110  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7111  }
7112 
7113  return SCIP_OKAY;
7114 }
7115 
7116 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7117 static
7119  SCIP_VAR* var, /**< problem variable to change */
7120  BMS_BLKMEM* blkmem, /**< block memory */
7121  SCIP_SET* set, /**< global SCIP settings */
7122  SCIP_LP* lp, /**< current LP data */
7123  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7124  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7125  SCIP_Real oldbound, /**< old upper bound for variable */
7126  SCIP_Real newbound /**< new upper bound for variable */
7127  )
7128 {
7129  assert(var != NULL);
7130  assert(var->eventfilter != NULL);
7131  assert(SCIPvarIsTransformed(var));
7132  assert(!SCIPsetIsEQ(set, oldbound, newbound));
7133  assert(set != NULL);
7134  assert(var->scip == set->scip);
7135 
7136  /* check, if the variable is being tracked for bound changes
7137  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7138  */
7139  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7142  {
7143  SCIP_EVENT* event;
7144 
7145  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7146 
7147  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7148  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7149  }
7150 
7151  return SCIP_OKAY;
7152 }
7153 
7154 /* forward declaration, because both methods call each other recursively */
7155 
7156 /* performs the current change in upper bound, changes all parents accordingly */
7157 static
7159  SCIP_VAR* var, /**< problem variable to change */
7160  BMS_BLKMEM* blkmem, /**< block memory */
7161  SCIP_SET* set, /**< global SCIP settings */
7162  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7163  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7164  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7165  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7166  SCIP_Real newbound /**< new bound for variable */
7167  );
7168 
7169 /** performs the current change in lower bound, changes all parents accordingly */
7170 static
7172  SCIP_VAR* var, /**< problem variable to change */
7173  BMS_BLKMEM* blkmem, /**< block memory */
7174  SCIP_SET* set, /**< global SCIP settings */
7175  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7176  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7177  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7178  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7179  SCIP_Real newbound /**< new bound for variable */
7180  )
7181 {
7182  SCIP_VAR* parentvar;
7183  SCIP_Real oldbound;
7184  int i;
7185 
7186  assert(var != NULL);
7187  assert(set != NULL);
7188  assert(var->scip == set->scip);
7189  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7190  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7192 
7193  /* check that the bound is feasible */
7194  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7195  /* adjust bound to integral value if variable is of integral type */
7196  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7197 
7198  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7199  {
7200  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7201  newbound = MIN(newbound, var->locdom.ub);
7202 
7203  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7204  newbound = MAX(newbound, var->glbdom.lb);
7205  }
7206  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7207 
7208  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7209 
7210  if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7211  return SCIP_OKAY;
7212  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
7213  newbound = var->glbdom.lb;
7214 
7215  /* change the bound */
7216  oldbound = var->locdom.lb;
7217  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7218  var->locdom.lb = newbound;
7219 
7220  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7221  * once update the statistic
7222  */
7223  if( stat != NULL )
7224  SCIPstatIncrement(stat, set, domchgcount);
7225 
7226  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7227  {
7228  /* merges overlapping holes into single holes, moves bounds respectively */
7229  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7230  }
7231 
7232  /* issue bound change event */
7233  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7234  if( var->eventfilter != NULL )
7235  {
7236  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7237  }
7238 
7239  /* process parent variables */
7240  for( i = 0; i < var->nparentvars; ++i )
7241  {
7242  parentvar = var->parentvars[i];
7243  assert(parentvar != NULL);
7244 
7245  switch( SCIPvarGetStatus(parentvar) )
7246  {
7248  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7249  break;
7250 
7251  case SCIP_VARSTATUS_COLUMN:
7252  case SCIP_VARSTATUS_LOOSE:
7253  case SCIP_VARSTATUS_FIXED:
7255  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7256  return SCIP_INVALIDDATA;
7257 
7258  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7259  assert(parentvar->data.aggregate.var == var);
7260  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7261  {
7262  SCIP_Real parentnewbound;
7263 
7264  /* a > 0 -> change lower bound of y */
7265  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, -oldbound))
7266  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7267  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7268 
7269  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7270  {
7271  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7272  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7273  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7274  * as a result, the parent's lower bound is set to it's upper bound, and not above
7275  */
7276  if( parentnewbound > parentvar->glbdom.ub )
7277  {
7278  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7279  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7280  parentnewbound = parentvar->glbdom.ub;
7281  }
7282  }
7283  else
7284  parentnewbound = newbound;
7285  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7286  }
7287  else
7288  {
7289  SCIP_Real parentnewbound;
7290 
7291  /* a < 0 -> change upper bound of y */
7292  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7293  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, -oldbound))
7294  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7295  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7296 
7297  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7298  {
7299  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7300  /* 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
7301  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7302  * as a result, the parent's upper bound is set to it's lower bound, and not below
7303  */
7304  if( parentnewbound < parentvar->glbdom.lb )
7305  {
7306  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7307  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7308  parentnewbound = parentvar->glbdom.lb;
7309  }
7310  }
7311  else
7312  parentnewbound = -newbound;
7313  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7314  }
7315  break;
7316 
7317  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7318  assert(parentvar->negatedvar != NULL);
7319  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7320  assert(parentvar->negatedvar->negatedvar == parentvar);
7321  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7322  parentvar->data.negate.constant - newbound) );
7323  break;
7324 
7325  default:
7326  SCIPerrorMessage("unknown variable status\n");
7327  return SCIP_INVALIDDATA;
7328  }
7329  }
7330 
7331  return SCIP_OKAY;
7332 }
7333 
7334 /** performs the current change in upper bound, changes all parents accordingly */
7335 static
7337  SCIP_VAR* var, /**< problem variable to change */
7338  BMS_BLKMEM* blkmem, /**< block memory */
7339  SCIP_SET* set, /**< global SCIP settings */
7340  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7341  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7342  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7343  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7344  SCIP_Real newbound /**< new bound for variable */
7345  )
7346 {
7347  SCIP_VAR* parentvar;
7348  SCIP_Real oldbound;
7349  int i;
7350 
7351  assert(var != NULL);
7352  assert(set != NULL);
7353  assert(var->scip == set->scip);
7354  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)))
7355  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && SCIPsetIsIntegral(set, newbound))
7357 
7358  /* check that the bound is feasible */
7359  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7360  /* adjust bound to integral value if variable is of integral type */
7361  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7362 
7363  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7364  {
7365  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7366  newbound = MAX(newbound, var->locdom.lb);
7367 
7368  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7369  newbound = MIN(newbound, var->glbdom.ub);
7370  }
7371  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7372 
7373  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7374 
7375  if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7376  return SCIP_OKAY;
7377  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
7378  newbound = var->glbdom.ub;
7379 
7380  /* change the bound */
7381  oldbound = var->locdom.ub;
7382  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7383  var->locdom.ub = newbound;
7384 
7385  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7386  * once update the statistic
7387  */
7388  if( stat != NULL )
7389  SCIPstatIncrement(stat, set, domchgcount);
7390 
7391  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7392  {
7393  /* merges overlapping holes into single holes, moves bounds respectively */
7394  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7395  }
7396 
7397  /* issue bound change event */
7398  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7399  if( var->eventfilter != NULL )
7400  {
7401  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7402  }
7403 
7404  /* process parent variables */
7405  for( i = 0; i < var->nparentvars; ++i )
7406  {
7407  parentvar = var->parentvars[i];
7408  assert(parentvar != NULL);
7409 
7410  switch( SCIPvarGetStatus(parentvar) )
7411  {
7413  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7414  break;
7415 
7416  case SCIP_VARSTATUS_COLUMN:
7417  case SCIP_VARSTATUS_LOOSE:
7418  case SCIP_VARSTATUS_FIXED:
7420  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7421  return SCIP_INVALIDDATA;
7422 
7423  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7424  assert(parentvar->data.aggregate.var == var);
7425  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7426  {
7427  SCIP_Real parentnewbound;
7428 
7429  /* a > 0 -> change upper bound of x */
7430  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, oldbound))
7431  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7432  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7433  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7434  {
7435  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7436  /* 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
7437  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7438  * as a result, the parent's upper bound is set to it's lower bound, and not below
7439  */
7440  if( parentnewbound < parentvar->glbdom.lb )
7441  {
7442  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7443  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7444  parentnewbound = parentvar->glbdom.lb;
7445  }
7446  }
7447  else
7448  parentnewbound = newbound;
7449  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7450  }
7451  else
7452  {
7453  SCIP_Real parentnewbound;
7454 
7455  /* a < 0 -> change lower bound of x */
7456  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7457  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, oldbound))
7458  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7459  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7460  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7461  {
7462  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7463  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7464  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7465  * as a result, the parent's lower bound is set to it's upper bound, and not above
7466  */
7467  if( parentnewbound > parentvar->glbdom.ub )
7468  {
7469  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7470  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7471  parentnewbound = parentvar->glbdom.ub;
7472  }
7473  }
7474  else
7475  parentnewbound = -newbound;
7476  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7477  }
7478  break;
7479 
7480  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7481  assert(parentvar->negatedvar != NULL);
7482  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7483  assert(parentvar->negatedvar->negatedvar == parentvar);
7484  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7485  parentvar->data.negate.constant - newbound) );
7486  break;
7487 
7488  default:
7489  SCIPerrorMessage("unknown variable status\n");
7490  return SCIP_INVALIDDATA;
7491  }
7492  }
7493 
7494  return SCIP_OKAY;
7495 }
7496 
7497 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7498  * information in variable
7499  */
7501  SCIP_VAR* var, /**< problem variable to change */
7502  BMS_BLKMEM* blkmem, /**< block memory */
7503  SCIP_SET* set, /**< global SCIP settings */
7504  SCIP_STAT* stat, /**< problem statistics */
7505  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7506  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7507  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7508  SCIP_Real newbound /**< new bound for variable */
7509  )
7510 {
7511  assert(var != NULL);
7512  assert(blkmem != NULL);
7513  assert(set != NULL);
7514  assert(var->scip == set->scip);
7515 
7516  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7517  * of the domain within feastol
7518  */
7519  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7520 
7521  /* adjust bound to integral value if variable is of integral type */
7522  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7523 
7524  /* check that the adjusted bound is feasible */
7525  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7526 
7527  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7528  {
7529  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7530  newbound = MIN(newbound, var->locdom.ub);
7531  }
7532  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7533 
7534  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7535 
7536  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) )
7537  return SCIP_OKAY;
7538 
7539  /* change bounds of attached variables */
7540  switch( SCIPvarGetStatus(var) )
7541  {
7543  if( var->data.original.transvar != NULL )
7544  {
7545  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7546  newbound) );
7547  }
7548  else
7549  {
7550  assert(set->stage == SCIP_STAGE_PROBLEM);
7551  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7552  }
7553  break;
7554 
7555  case SCIP_VARSTATUS_COLUMN:
7556  case SCIP_VARSTATUS_LOOSE:
7557  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7558  break;
7559 
7560  case SCIP_VARSTATUS_FIXED:
7561  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7562  return SCIP_INVALIDDATA;
7563 
7564  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7565  assert(var->data.aggregate.var != NULL);
7566  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7567  {
7568  SCIP_Real childnewbound;
7569 
7570  /* a > 0 -> change lower bound of y */
7571  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7572  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7574  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7575  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7576  else
7577  childnewbound = newbound;
7578  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7579  childnewbound) );
7580  }
7581  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7582  {
7583  SCIP_Real childnewbound;
7584 
7585  /* a < 0 -> change upper bound of y */
7586  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7587  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7589  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7590  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7591  else
7592  childnewbound = -newbound;
7593  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7594  childnewbound) );
7595  }
7596  else
7597  {
7598  SCIPerrorMessage("scalar is zero in aggregation\n");
7599  return SCIP_INVALIDDATA;
7600  }
7601  break;
7602 
7604  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7605  return SCIP_INVALIDDATA;
7606 
7607  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7608  assert(var->negatedvar != NULL);
7610  assert(var->negatedvar->negatedvar == var);
7611  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7612  var->data.negate.constant - newbound) );
7613  break;
7614 
7615  default:
7616  SCIPerrorMessage("unknown variable status\n");
7617  return SCIP_INVALIDDATA;
7618  }
7619 
7620  return SCIP_OKAY;
7621 }
7622 
7623 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7624  * information in variable
7625  */
7627  SCIP_VAR* var, /**< problem variable to change */
7628  BMS_BLKMEM* blkmem, /**< block memory */
7629  SCIP_SET* set, /**< global SCIP settings */
7630  SCIP_STAT* stat, /**< problem statistics */
7631  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7632  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7633  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7634  SCIP_Real newbound /**< new bound for variable */
7635  )
7636 {
7637  assert(var != NULL);
7638  assert(blkmem != NULL);
7639  assert(set != NULL);
7640  assert(var->scip == set->scip);
7641 
7642  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7643  * of the domain within feastol
7644  */
7645  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7646 
7647  /* adjust bound to integral value if variable is of integral type */
7648  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7649 
7650  /* check that the adjusted bound is feasible */
7651  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7652 
7653  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7654  {
7655  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7656  newbound = MAX(newbound, var->locdom.lb);
7657  }
7658  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7659 
7660  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7661 
7662  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) )
7663  return SCIP_OKAY;
7664 
7665  /* change bounds of attached variables */
7666  switch( SCIPvarGetStatus(var) )
7667  {
7669  if( var->data.original.transvar != NULL )
7670  {
7671  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7672  }
7673  else
7674  {
7675  assert(set->stage == SCIP_STAGE_PROBLEM);
7676  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7677  }
7678  break;
7679 
7680  case SCIP_VARSTATUS_COLUMN:
7681  case SCIP_VARSTATUS_LOOSE:
7682  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7683  break;
7684 
7685  case SCIP_VARSTATUS_FIXED:
7686  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7687  return SCIP_INVALIDDATA;
7688 
7689  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7690  assert(var->data.aggregate.var != NULL);
7691  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7692  {
7693  SCIP_Real childnewbound;
7694 
7695  /* a > 0 -> change upper bound of y */
7696  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7697  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7699  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7700  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7701  else
7702  childnewbound = newbound;
7703  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7704  childnewbound) );
7705  }
7706  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7707  {
7708  SCIP_Real childnewbound;
7709 
7710  /* a < 0 -> change lower bound of y */
7711  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7712  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7714  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7715  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7716  else
7717  childnewbound = -newbound;
7718  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7719  childnewbound) );
7720  }
7721  else
7722  {
7723  SCIPerrorMessage("scalar is zero in aggregation\n");
7724  return SCIP_INVALIDDATA;
7725  }
7726  break;
7727 
7729  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7730  return SCIP_INVALIDDATA;
7731 
7732  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7733  assert(var->negatedvar != NULL);
7735  assert(var->negatedvar->negatedvar == var);
7736  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7737  var->data.negate.constant - newbound) );
7738  break;
7739 
7740  default:
7741  SCIPerrorMessage("unknown variable status\n");
7742  return SCIP_INVALIDDATA;
7743  }
7744 
7745  return SCIP_OKAY;
7746 }
7747 
7748 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7749  * information in variable
7750  */
7752  SCIP_VAR* var, /**< problem variable to change */
7753  BMS_BLKMEM* blkmem, /**< block memory */
7754  SCIP_SET* set, /**< global SCIP settings */
7755  SCIP_STAT* stat, /**< problem statistics */
7756  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7757  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7758  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7759  SCIP_Real newbound, /**< new bound for variable */
7760  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7761  )
7762 {
7763  /* apply bound change to the LP data */
7764  switch( boundtype )
7765  {
7766  case SCIP_BOUNDTYPE_LOWER:
7767  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7768  case SCIP_BOUNDTYPE_UPPER:
7769  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7770  default:
7771  SCIPerrorMessage("unknown bound type\n");
7772  return SCIP_INVALIDDATA;
7773  }
7774 }
7775 
7776 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7778  SCIP_VAR* var, /**< problem variable to change */
7779  SCIP_SET* set, /**< global SCIP settings */
7780  SCIP_LP* lp, /**< current LP data */
7781  SCIP_Real newbound /**< new bound for variable */
7782  )
7783 {
7784  assert(var != NULL);
7785  assert(set != NULL);
7786  assert(var->scip == set->scip);
7787  assert(lp != NULL);
7788  assert(SCIPlpDiving(lp));
7789 
7790  /* adjust bound for integral variables */
7791  SCIPvarAdjustLb(var, set, &newbound);
7792 
7793  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7794 
7795  /* change bounds of attached variables */
7796  switch( SCIPvarGetStatus(var) )
7797  {
7799  assert(var->data.original.transvar != NULL);
7800  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7801  break;
7802 
7803  case SCIP_VARSTATUS_COLUMN:
7804  assert(var->data.col != NULL);
7805  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7806  break;
7807 
7808  case SCIP_VARSTATUS_LOOSE:
7809  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7810  return SCIP_INVALIDDATA;
7811 
7812  case SCIP_VARSTATUS_FIXED:
7813  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7814  return SCIP_INVALIDDATA;
7815 
7816  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7817  assert(var->data.aggregate.var != NULL);
7818  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7819  {
7820  SCIP_Real childnewbound;
7821 
7822  /* a > 0 -> change lower bound of y */
7823  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7824  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7825  else
7826  childnewbound = newbound;
7827  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7828  }
7829  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7830  {
7831  SCIP_Real childnewbound;
7832 
7833  /* a < 0 -> change upper bound of y */
7834  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7835  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7836  else
7837  childnewbound = -newbound;
7838  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7839  }
7840  else
7841  {
7842  SCIPerrorMessage("scalar is zero in aggregation\n");
7843  return SCIP_INVALIDDATA;
7844  }
7845  break;
7846 
7848  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7849  return SCIP_INVALIDDATA;
7850 
7851  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7852  assert(var->negatedvar != NULL);
7854  assert(var->negatedvar->negatedvar == var);
7855  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7856  break;
7857 
7858  default:
7859  SCIPerrorMessage("unknown variable status\n");
7860  return SCIP_INVALIDDATA;
7861  }
7862 
7863  return SCIP_OKAY;
7864 }
7865 
7866 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
7868  SCIP_VAR* var, /**< problem variable to change */
7869  SCIP_SET* set, /**< global SCIP settings */
7870  SCIP_LP* lp, /**< current LP data */
7871  SCIP_Real newbound /**< new bound for variable */
7872  )
7873 {
7874  assert(var != NULL);
7875  assert(set != NULL);
7876  assert(var->scip == set->scip);
7877  assert(lp != NULL);
7878  assert(SCIPlpDiving(lp));
7879 
7880  /* adjust bound for integral variables */
7881  SCIPvarAdjustUb(var, set, &newbound);
7882 
7883  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
7884 
7885  /* change bounds of attached variables */
7886  switch( SCIPvarGetStatus(var) )
7887  {
7889  assert(var->data.original.transvar != NULL);
7890  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
7891  break;
7892 
7893  case SCIP_VARSTATUS_COLUMN:
7894  assert(var->data.col != NULL);
7895  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
7896  break;
7897 
7898  case SCIP_VARSTATUS_LOOSE:
7899  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7900  return SCIP_INVALIDDATA;
7901 
7902  case SCIP_VARSTATUS_FIXED:
7903  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7904  return SCIP_INVALIDDATA;
7905 
7906  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7907  assert(var->data.aggregate.var != NULL);
7908  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7909  {
7910  SCIP_Real childnewbound;
7911 
7912  /* a > 0 -> change upper bound of y */
7913  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7914  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7915  else
7916  childnewbound = newbound;
7917  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7918  }
7919  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7920  {
7921  SCIP_Real childnewbound;
7922 
7923  /* a < 0 -> change lower bound of y */
7924  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7925  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7926  else
7927  childnewbound = -newbound;
7928  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7929  }
7930  else
7931  {
7932  SCIPerrorMessage("scalar is zero in aggregation\n");
7933  return SCIP_INVALIDDATA;
7934  }
7935  break;
7936 
7938  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7939  return SCIP_INVALIDDATA;
7940 
7941  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7942  assert(var->negatedvar != NULL);
7944  assert(var->negatedvar->negatedvar == var);
7945  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7946  break;
7947 
7948  default:
7949  SCIPerrorMessage("unknown variable status\n");
7950  return SCIP_INVALIDDATA;
7951  }
7952 
7953  return SCIP_OKAY;
7954 }
7955 
7956 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
7957  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
7958  * not updated if bounds of aggregation variables are changing
7959  *
7960  * calling this function for a non-multi-aggregated variable is not allowed
7961  */
7963  SCIP_VAR* var, /**< problem variable */
7964  SCIP_SET* set /**< global SCIP settings */
7965  )
7966 {
7967  int i;
7968  SCIP_Real lb;
7969  SCIP_Real bnd;
7970  SCIP_VAR* aggrvar;
7971  SCIP_Bool posinf;
7972  SCIP_Bool neginf;
7973 
7974  assert(var != NULL);
7975  assert(set != NULL);
7976  assert(var->scip == set->scip);
7978 
7979  posinf = FALSE;
7980  neginf = FALSE;
7981  lb = var->data.multaggr.constant;
7982  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
7983  {
7984  aggrvar = var->data.multaggr.vars[i];
7985  if( var->data.multaggr.scalars[i] > 0.0 )
7986  {
7987  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
7988 
7989  if( SCIPsetIsInfinity(set, bnd) )
7990  posinf = TRUE;
7991  else if( SCIPsetIsInfinity(set, -bnd) )
7992  neginf = TRUE;
7993  else
7994  lb += var->data.multaggr.scalars[i] * bnd;
7995  }
7996  else
7997  {
7998  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
7999 
8000  if( SCIPsetIsInfinity(set, -bnd) )
8001  posinf = TRUE;
8002  else if( SCIPsetIsInfinity(set, bnd) )
8003  neginf = TRUE;
8004  else
8005  lb += var->data.multaggr.scalars[i] * bnd;
8006  }
8007 
8008  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8009  * variable
8010  */
8011  if( neginf )
8012  return SCIPvarGetLbLocal(var);
8013  }
8014 
8015  /* if positive infinity flag was set to true return infinity */
8016  if( posinf )
8017  return SCIPsetInfinity(set);
8018 
8019  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8020 }
8021 
8022 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8023  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8024  * not updated if bounds of aggregation variables are changing
8025  *
8026  * calling this function for a non-multi-aggregated variable is not allowed
8027  */
8029  SCIP_VAR* var, /**< problem variable */
8030  SCIP_SET* set /**< global SCIP settings */
8031  )
8032 {
8033  int i;
8034  SCIP_Real ub;
8035  SCIP_Real bnd;
8036  SCIP_VAR* aggrvar;
8037  SCIP_Bool posinf;
8038  SCIP_Bool neginf;
8039 
8040  assert(var != NULL);
8041  assert(set != NULL);
8042  assert(var->scip == set->scip);
8044 
8045  posinf = FALSE;
8046  neginf = FALSE;
8047  ub = var->data.multaggr.constant;
8048  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8049  {
8050  aggrvar = var->data.multaggr.vars[i];
8051  if( var->data.multaggr.scalars[i] > 0.0 )
8052  {
8053  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8054 
8055  if( SCIPsetIsInfinity(set, bnd) )
8056  posinf = TRUE;
8057  else if( SCIPsetIsInfinity(set, -bnd) )
8058  neginf = TRUE;
8059  else
8060  ub += var->data.multaggr.scalars[i] * bnd;
8061  }
8062  else
8063  {
8064  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8065 
8066  if( SCIPsetIsInfinity(set, -bnd) )
8067  posinf = TRUE;
8068  else if( SCIPsetIsInfinity(set, bnd) )
8069  neginf = TRUE;
8070  else
8071  ub += var->data.multaggr.scalars[i] * bnd;
8072  }
8073 
8074  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8075  * variable
8076  */
8077  if( posinf )
8078  return SCIPvarGetUbLocal(var);
8079  }
8080 
8081  /* if negative infinity flag was set to true return -infinity */
8082  if( neginf )
8083  return -SCIPsetInfinity(set);
8084 
8085  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8086 }
8087 
8088 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8089  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8090  * not updated if bounds of aggregation variables are changing
8091  *
8092  * calling this function for a non-multi-aggregated variable is not allowed
8093  */
8095  SCIP_VAR* var, /**< problem variable */
8096  SCIP_SET* set /**< global SCIP settings */
8097  )
8098 {
8099  int i;
8100  SCIP_Real lb;
8101  SCIP_Real bnd;
8102  SCIP_VAR* aggrvar;
8103  SCIP_Bool posinf;
8104  SCIP_Bool neginf;
8105 
8106  assert(var != NULL);
8107  assert(set != NULL);
8108  assert(var->scip == set->scip);
8110 
8111  posinf = FALSE;
8112  neginf = FALSE;
8113  lb = var->data.multaggr.constant;
8114  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8115  {
8116  aggrvar = var->data.multaggr.vars[i];
8117  if( var->data.multaggr.scalars[i] > 0.0 )
8118  {
8119  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8120 
8121  if( SCIPsetIsInfinity(set, bnd) )
8122  posinf = TRUE;
8123  else if( SCIPsetIsInfinity(set, -bnd) )
8124  neginf = TRUE;
8125  else
8126  lb += var->data.multaggr.scalars[i] * bnd;
8127  }
8128  else
8129  {
8130  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8131 
8132  if( SCIPsetIsInfinity(set, -bnd) )
8133  posinf = TRUE;
8134  else if( SCIPsetIsInfinity(set, bnd) )
8135  neginf = TRUE;
8136  else
8137  lb += var->data.multaggr.scalars[i] * bnd;
8138  }
8139 
8140  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8141  * variable
8142  */
8143  if( neginf )
8144  return SCIPvarGetLbGlobal(var);
8145  }
8146 
8147  /* if positive infinity flag was set to true return infinity */
8148  if( posinf )
8149  return SCIPsetInfinity(set);
8150 
8151  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8152 }
8153 
8154 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8155  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8156  * not updated if bounds of aggregation variables are changing
8157  *
8158  * calling this function for a non-multi-aggregated variable is not allowed
8159  */
8161  SCIP_VAR* var, /**< problem variable */
8162  SCIP_SET* set /**< global SCIP settings */
8163  )
8164 {
8165  int i;
8166  SCIP_Real ub;
8167  SCIP_Real bnd;
8168  SCIP_VAR* aggrvar;
8169  SCIP_Bool posinf;
8170  SCIP_Bool neginf;
8171 
8172  assert(var != NULL);
8173  assert(set != NULL);
8174  assert(var->scip == set->scip);
8176 
8177  posinf = FALSE;
8178  neginf = FALSE;
8179  ub = var->data.multaggr.constant;
8180  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8181  {
8182  aggrvar = var->data.multaggr.vars[i];
8183  if( var->data.multaggr.scalars[i] > 0.0 )
8184  {
8185  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8186 
8187  if( SCIPsetIsInfinity(set, bnd) )
8188  posinf = TRUE;
8189  else if( SCIPsetIsInfinity(set, -bnd) )
8190  neginf = TRUE;
8191  else
8192  ub += var->data.multaggr.scalars[i] * bnd;
8193  }
8194  else
8195  {
8196  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8197 
8198  if( SCIPsetIsInfinity(set, -bnd) )
8199  posinf = TRUE;
8200  else if( SCIPsetIsInfinity(set, bnd) )
8201  neginf = TRUE;
8202  else
8203  ub += var->data.multaggr.scalars[i] * bnd;
8204  }
8205 
8206  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8207  * variable
8208  */
8209  if( posinf )
8210  return SCIPvarGetUbGlobal(var);
8211  }
8212 
8213  /* if negative infinity flag was set to true return -infinity */
8214  if( neginf )
8215  return -SCIPsetInfinity(set);
8216 
8217  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8218 }
8219 
8220 /** adds a hole to the original domain of the variable */
8222  SCIP_VAR* var, /**< problem variable */
8223  BMS_BLKMEM* blkmem, /**< block memory */
8224  SCIP_SET* set, /**< global SCIP settings */
8225  SCIP_Real left, /**< left bound of open interval in new hole */
8226  SCIP_Real right /**< right bound of open interval in new hole */
8227  )
8228 {
8229  SCIP_Bool added;
8230 
8231  assert(var != NULL);
8232  assert(!SCIPvarIsTransformed(var));
8234  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8235  assert(set != NULL);
8236  assert(var->scip == set->scip);
8237  assert(set->stage == SCIP_STAGE_PROBLEM);
8238 
8239  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8240 
8241  if( SCIPsetIsEQ(set, left, right) )
8242  return SCIP_OKAY;
8243 
8244  /* the interval should not be empty */
8245  assert(SCIPsetIsLT(set, left, right));
8246 
8247  /* the the interval bound should already be adjusted */
8248  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8249  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8250 
8251  /* the the interval should lay between the lower and upper bound */
8252  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8253  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8254 
8255  /* add domain hole */
8256  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8257 
8258  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8259  if( added )
8260  {
8261  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8262  }
8263 
8264  /**@todo add hole in parent and child variables (just like with bound changes);
8265  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8266  */
8267 
8268  return SCIP_OKAY;
8269 }
8270 
8271 /** performs the current add of domain, changes all parents accordingly */
8272 static
8274  SCIP_VAR* var, /**< problem variable */
8275  BMS_BLKMEM* blkmem, /**< block memory */
8276  SCIP_SET* set, /**< global SCIP settings */
8277  SCIP_STAT* stat, /**< problem statistics */
8278  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8279  SCIP_Real left, /**< left bound of open interval in new hole */
8280  SCIP_Real right, /**< right bound of open interval in new hole */
8281  SCIP_Bool* added /**< pointer to store whether the hole was added */
8282  )
8283 {
8284  SCIP_VAR* parentvar;
8285  SCIP_Real newlb;
8286  SCIP_Real newub;
8287  int i;
8288 
8289  assert(var != NULL);
8290  assert(added != NULL);
8291  assert(blkmem != NULL);
8292 
8293  /* the interval should not be empty */
8294  assert(SCIPsetIsLT(set, left, right));
8295 
8296  /* the interval bound should already be adjusted */
8297  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8298  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8299 
8300  /* the interval should lay between the lower and upper bound */
8301  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8302  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8303 
8304  /* @todo add debugging mechanism for holes when using a debugging solution */
8305 
8306  /* add hole to hole list */
8307  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8308 
8309  /* check if the hole is redundant */
8310  if( !(*added) )
8311  return SCIP_OKAY;
8312 
8313  /* current bounds */
8314  newlb = var->glbdom.lb;
8315  newub = var->glbdom.ub;
8316 
8317  /* merge domain holes */
8318  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8319 
8320  /* the bound should not be changed */
8321  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8322  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8323 
8324  /* issue bound change event */
8325  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8326  if( var->eventfilter != NULL )
8327  {
8328  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8329  }
8330 
8331  /* process parent variables */
8332  for( i = 0; i < var->nparentvars; ++i )
8333  {
8334  SCIP_Real parentnewleft;
8335  SCIP_Real parentnewright;
8336  SCIP_Bool localadded;
8337 
8338  parentvar = var->parentvars[i];
8339  assert(parentvar != NULL);
8340 
8341  switch( SCIPvarGetStatus(parentvar) )
8342  {
8344  parentnewleft = left;
8345  parentnewright = right;
8346  break;
8347 
8348  case SCIP_VARSTATUS_COLUMN:
8349  case SCIP_VARSTATUS_LOOSE:
8350  case SCIP_VARSTATUS_FIXED:
8352  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8353  return SCIP_INVALIDDATA;
8354 
8355  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8356  assert(parentvar->data.aggregate.var == var);
8357 
8358  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8359  {
8360  /* a > 0 -> change upper bound of x */
8361  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8362  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8363  }
8364  else
8365  {
8366  /* a < 0 -> change lower bound of x */
8367  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8368 
8369  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8370  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8371  }
8372  break;
8373 
8374  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8375  assert(parentvar->negatedvar != NULL);
8376  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8377  assert(parentvar->negatedvar->negatedvar == parentvar);
8378 
8379  parentnewright = -left + parentvar->data.negate.constant;
8380  parentnewleft = -right + parentvar->data.negate.constant;
8381  break;
8382 
8383  default:
8384  SCIPerrorMessage("unknown variable status\n");
8385  return SCIP_INVALIDDATA;
8386  }
8387 
8388  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8389 
8390  /* perform hole added for parent variable */
8391  assert(blkmem != NULL);
8392  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8393  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8394  parentnewleft, parentnewright, &localadded) );
8395  assert(localadded);
8396  }
8397 
8398  return SCIP_OKAY;
8399 }
8400 
8401 /** adds a hole to the variable's global and local domain */
8403  SCIP_VAR* var, /**< problem variable */
8404  BMS_BLKMEM* blkmem, /**< block memory */
8405  SCIP_SET* set, /**< global SCIP settings */
8406  SCIP_STAT* stat, /**< problem statistics */
8407  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8408  SCIP_Real left, /**< left bound of open interval in new hole */
8409  SCIP_Real right, /**< right bound of open interval in new hole */
8410  SCIP_Bool* added /**< pointer to store whether the hole was added */
8411  )
8412 {
8413  SCIP_Real childnewleft;
8414  SCIP_Real childnewright;
8415 
8416  assert(var != NULL);
8417  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8418  assert(blkmem != NULL);
8419  assert(added != NULL);
8420 
8421  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8422 
8423  /* the interval should not be empty */
8424  assert(SCIPsetIsLT(set, left, right));
8425 
8426  /* the the interval bound should already be adjusted */
8427  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8428  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8429 
8430  /* the the interval should lay between the lower and upper bound */
8431  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8432  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8433 
8434  /* change bounds of attached variables */
8435  switch( SCIPvarGetStatus(var) )
8436  {
8438  if( var->data.original.transvar != NULL )
8439  {
8440  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8441  left, right, added) );
8442  }
8443  else
8444  {
8445  assert(set->stage == SCIP_STAGE_PROBLEM);
8446 
8447  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8448  if( *added )
8449  {
8450  SCIP_Bool localadded;
8451 
8452  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8453  }
8454  }
8455  break;
8456 
8457  case SCIP_VARSTATUS_COLUMN:
8458  case SCIP_VARSTATUS_LOOSE:
8459  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8460  if( *added )
8461  {
8462  SCIP_Bool localadded;
8463 
8464  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8465  }
8466  break;
8467 
8468  case SCIP_VARSTATUS_FIXED:
8469  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8470  return SCIP_INVALIDDATA;
8471 
8472  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8473  assert(var->data.aggregate.var != NULL);
8474 
8475  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8476  {
8477  /* a > 0 -> change lower bound of y */
8478  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8479  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8480  }
8481  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8482  {
8483  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8484  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8485  }
8486  else
8487  {
8488  SCIPerrorMessage("scalar is zero in aggregation\n");
8489  return SCIP_INVALIDDATA;
8490  }
8491  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8492  childnewleft, childnewright, added) );
8493  break;
8494 
8496  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8497  return SCIP_INVALIDDATA;
8498 
8499  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8500  assert(var->negatedvar != NULL);
8502  assert(var->negatedvar->negatedvar == var);
8503 
8504  childnewright = -left + var->data.negate.constant;
8505  childnewleft = -right + var->data.negate.constant;
8506 
8507  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8508  childnewleft, childnewright, added) );
8509  break;
8510 
8511  default:
8512  SCIPerrorMessage("unknown variable status\n");
8513  return SCIP_INVALIDDATA;
8514  }
8515 
8516  return SCIP_OKAY;
8517 }
8518 
8519 /** performs the current add of domain, changes all parents accordingly */
8520 static
8522  SCIP_VAR* var, /**< problem variable */
8523  BMS_BLKMEM* blkmem, /**< block memory */
8524  SCIP_SET* set, /**< global SCIP settings */
8525  SCIP_STAT* stat, /**< problem statistics */
8526  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8527  SCIP_Real left, /**< left bound of open interval in new hole */
8528  SCIP_Real right, /**< right bound of open interval in new hole */
8529  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8530  )
8531 {
8532  SCIP_VAR* parentvar;
8533  SCIP_Real newlb;
8534  SCIP_Real newub;
8535  int i;
8536 
8537  assert(var != NULL);
8538  assert(added != NULL);
8539  assert(blkmem != NULL);
8540 
8541  /* the interval should not be empty */
8542  assert(SCIPsetIsLT(set, left, right));
8543 
8544  /* the the interval bound should already be adjusted */
8545  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8546  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8547 
8548  /* the the interval should lay between the lower and upper bound */
8549  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8550  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8551 
8552  /* add hole to hole list */
8553  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8554 
8555  /* check if the hole is redundant */
8556  if( !(*added) )
8557  return SCIP_OKAY;
8558 
8559  /* current bounds */
8560  newlb = var->locdom.lb;
8561  newub = var->locdom.ub;
8562 
8563  /* merge domain holes */
8564  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8565 
8566  /* the bound should not be changed */
8567  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8568  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8569 
8570 #if 0
8571  /* issue bound change event */
8572  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8573  if( var->eventfilter != NULL )
8574  {
8575  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8576  }
8577 #endif
8578 
8579  /* process parent variables */
8580  for( i = 0; i < var->nparentvars; ++i )
8581  {
8582  SCIP_Real parentnewleft;
8583  SCIP_Real parentnewright;
8584  SCIP_Bool localadded;
8585 
8586  parentvar = var->parentvars[i];
8587  assert(parentvar != NULL);
8588 
8589  switch( SCIPvarGetStatus(parentvar) )
8590  {
8592  parentnewleft = left;
8593  parentnewright = right;
8594  break;
8595 
8596  case SCIP_VARSTATUS_COLUMN:
8597  case SCIP_VARSTATUS_LOOSE:
8598  case SCIP_VARSTATUS_FIXED:
8600  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8601  return SCIP_INVALIDDATA;
8602 
8603  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8604  assert(parentvar->data.aggregate.var == var);
8605 
8606  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8607  {
8608  /* a > 0 -> change upper bound of x */
8609  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8610  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8611  }
8612  else
8613  {
8614  /* a < 0 -> change lower bound of x */
8615  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8616 
8617  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8618  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8619  }
8620  break;
8621 
8622  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8623  assert(parentvar->negatedvar != NULL);
8624  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8625  assert(parentvar->negatedvar->negatedvar == parentvar);
8626 
8627  parentnewright = -left + parentvar->data.negate.constant;
8628  parentnewleft = -right + parentvar->data.negate.constant;
8629  break;
8630 
8631  default:
8632  SCIPerrorMessage("unknown variable status\n");
8633  return SCIP_INVALIDDATA;
8634  }
8635 
8636  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8637 
8638  /* perform hole added for parent variable */
8639  assert(blkmem != NULL);
8640  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8641  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8642  parentnewleft, parentnewright, &localadded) );
8643  assert(localadded);
8644  }
8645 
8646  return SCIP_OKAY;
8647 }
8648 
8649 /** adds a hole to the variable's current local domain */
8651  SCIP_VAR* var, /**< problem variable */
8652  BMS_BLKMEM* blkmem, /**< block memory */
8653  SCIP_SET* set, /**< global SCIP settings */
8654  SCIP_STAT* stat, /**< problem statistics */
8655  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8656  SCIP_Real left, /**< left bound of open interval in new hole */
8657  SCIP_Real right, /**< right bound of open interval in new hole */
8658  SCIP_Bool* added /**< pointer to store whether the hole was added */
8659  )
8660 {
8661  SCIP_Real childnewleft;
8662  SCIP_Real childnewright;
8663 
8664  assert(var != NULL);
8665 
8666  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8667 
8668  assert(set != NULL);
8669  assert(var->scip == set->scip);
8670  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8671  assert(blkmem != NULL);
8672  assert(added != NULL);
8673 
8674  /* the interval should not be empty */
8675  assert(SCIPsetIsLT(set, left, right));
8676 
8677  /* the the interval bound should already be adjusted */
8678  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8679  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8680 
8681  /* the the interval should lay between the lower and upper bound */
8682  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8683  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8684 
8685  /* change bounds of attached variables */
8686  switch( SCIPvarGetStatus(var) )
8687  {
8689  if( var->data.original.transvar != NULL )
8690  {
8691  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8692  left, right, added) );
8693  }
8694  else
8695  {
8696  assert(set->stage == SCIP_STAGE_PROBLEM);
8697  SCIPstatIncrement(stat, set, domchgcount);
8698  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8699  }
8700  break;
8701 
8702  case SCIP_VARSTATUS_COLUMN:
8703  case SCIP_VARSTATUS_LOOSE:
8704  SCIPstatIncrement(stat, set, domchgcount);
8705  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8706  break;
8707 
8708  case SCIP_VARSTATUS_FIXED:
8709  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8710  return SCIP_INVALIDDATA;
8711 
8712  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8713  assert(var->data.aggregate.var != NULL);
8714 
8715  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8716  {
8717  /* a > 0 -> change lower bound of y */
8718  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8719  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8720  }
8721  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8722  {
8723  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8724  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8725  }
8726  else
8727  {
8728  SCIPerrorMessage("scalar is zero in aggregation\n");
8729  return SCIP_INVALIDDATA;
8730  }
8731  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8732  childnewleft, childnewright, added) );
8733  break;
8734 
8736  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8737  return SCIP_INVALIDDATA;
8738 
8739  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8740  assert(var->negatedvar != NULL);
8742  assert(var->negatedvar->negatedvar == var);
8743 
8744  childnewright = -left + var->data.negate.constant;
8745  childnewleft = -right + var->data.negate.constant;
8746 
8747  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8748  break;
8749 
8750  default:
8751  SCIPerrorMessage("unknown variable status\n");
8752  return SCIP_INVALIDDATA;
8753  }
8754 
8755  return SCIP_OKAY;
8756 }
8757 
8758 /** resets the global and local bounds of original variable to their original values */
8760  SCIP_VAR* var, /**< problem variable */
8761  BMS_BLKMEM* blkmem, /**< block memory */
8762  SCIP_SET* set, /**< global SCIP settings */
8763  SCIP_STAT* stat /**< problem statistics */
8764  )
8765 {
8766  assert(var != NULL);
8767  assert(set != NULL);
8768  assert(var->scip == set->scip);
8769  assert(SCIPvarIsOriginal(var));
8770  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8771  * the transformed variable has been fixed */
8772  assert(SCIPvarGetTransVar(var) == NULL);
8773 
8774  /* copy the original bounds back to the global and local bounds */
8775  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8776  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8777  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8778  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8779 
8780  /* free the global and local holelists and duplicate the original ones */
8781  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8782  holelistFree(&var->glbdom.holelist, blkmem);
8783  holelistFree(&var->locdom.holelist, blkmem);
8784  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8785  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8786 
8787  return SCIP_OKAY;
8788 }
8789 
8790 /** issues a IMPLADDED event on the given variable */
8791 static
8793  SCIP_VAR* var, /**< problem variable to change */
8794  BMS_BLKMEM* blkmem, /**< block memory */
8795  SCIP_SET* set, /**< global SCIP settings */
8796  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8797  )
8798 {
8799  SCIP_EVENT* event;
8800 
8801  assert(var != NULL);
8802 
8803  /* issue IMPLADDED event on variable */
8804  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8805  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8806 
8807  return SCIP_OKAY;
8808 }
8809 
8810 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8811 static
8813  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8814  BMS_BLKMEM* blkmem, /**< block memory */
8815  SCIP_SET* set, /**< global SCIP settings */
8816  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8817  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8818  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8819  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8820  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8821  )
8822 {
8823  SCIP_Bool added;
8824 
8825  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8826  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
8827  * variable of the aggregated variable might be the same as the one its gets aggregated too.
8828  *
8829  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
8830  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
8831  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
8832  * variable bound can be ignored.
8833  *
8834  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
8835  * equivalence of the variables should be checked here.
8836  */
8837  if( var == vbvar )
8838  {
8839  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
8840  * can be checked via the global bounds of the variable */
8841 #ifndef NDEBUG
8842  SCIP_Real lb;
8843  SCIP_Real ub;
8844 
8845  lb = SCIPvarGetLbGlobal(var);
8846  ub = SCIPvarGetUbGlobal(var);
8847 
8848  if(vbtype == SCIP_BOUNDTYPE_LOWER)
8849  {
8850  if( vbcoef > 0.0 )
8851  {
8852  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
8853  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
8854  }
8855  else
8856  {
8857  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
8858  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
8859  }
8860  }
8861  else
8862  {
8863  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
8864  if( vbcoef > 0.0 )
8865  {
8866  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
8867  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
8868  }
8869  else
8870  {
8871  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
8872  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
8873  }
8874  }
8875 #endif
8876  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
8877  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8878 
8879  return SCIP_OKAY;
8880  }
8881 
8882  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
8883  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8884 
8885  /* check variable bound on debugging solution */
8886  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
8887 
8888  /* perform the addition */
8889  if( vbtype == SCIP_BOUNDTYPE_LOWER )
8890  {
8891  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8892  }
8893  else
8894  {
8895  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8896  }
8897  var->closestvblpcount = -1;
8898 
8899  if( added )
8900  {
8901  /* issue IMPLADDED event */
8902  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
8903  }
8904 
8905  return SCIP_OKAY;
8906 }
8907 
8908 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
8909 static
8910 void checkImplic(
8911  SCIP_SET* set, /**< global SCIP settings */
8912  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8913  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8914  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8915  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
8916  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
8917  )
8918 {
8919  SCIP_Real impllb;
8920  SCIP_Real implub;
8921 
8922  assert(redundant != NULL);
8923  assert(infeasible != NULL);
8924 
8925  impllb = SCIPvarGetLbGlobal(implvar);
8926  implub = SCIPvarGetUbGlobal(implvar);
8927  if( impltype == SCIP_BOUNDTYPE_LOWER )
8928  {
8929  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
8930  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
8931  }
8932  else
8933  {
8934  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
8935  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
8936  }
8937 }
8938 
8939 /** applies the given implication, if it is not redundant */
8940 static
8942  BMS_BLKMEM* blkmem, /**< block memory */
8943  SCIP_SET* set, /**< global SCIP settings */
8944  SCIP_STAT* stat, /**< problem statistics */
8945  SCIP_PROB* transprob, /**< transformed problem */
8946  SCIP_PROB* origprob, /**< original problem */
8947  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
8948  SCIP_REOPT* reopt, /**< reoptimization data structure */
8949  SCIP_LP* lp, /**< current LP data */
8950  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
8951  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8952  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
8953  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
8954  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
8955  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
8956  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
8957  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
8958  )
8959 {
8960  SCIP_Real implub;
8961  SCIP_Real impllb;
8962 
8963  assert(infeasible != NULL);
8964 
8965  *infeasible = FALSE;
8966 
8967  implub = SCIPvarGetUbGlobal(implvar);
8968  impllb = SCIPvarGetLbGlobal(implvar);
8969  if( impltype == SCIP_BOUNDTYPE_LOWER )
8970  {
8971  if( SCIPsetIsFeasGT(set, implbound, implub) )
8972  {
8973  /* the implication produces a conflict: the problem is infeasible */
8974  *infeasible = TRUE;
8975  }
8976  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
8977  {
8978  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
8979  * with the local bound, in this case we need to store the bound change as pending bound change
8980  */
8981  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
8982  {
8983  assert(tree != NULL);
8984  assert(transprob != NULL);
8985  assert(SCIPprobIsTransformed(transprob));
8986 
8987  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
8988  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
8989  }
8990  else
8991  {
8992  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
8993  }
8994 
8995  if( nbdchgs != NULL )
8996  (*nbdchgs)++;
8997  }
8998  }
8999  else
9000  {
9001  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9002  {
9003  /* the implication produces a conflict: the problem is infeasible */
9004  *infeasible = TRUE;
9005  }
9006  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9007  {
9008  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9009  * with the local bound, in this case we need to store the bound change as pending bound change
9010  */
9011  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9012  {
9013  assert(tree != NULL);
9014  assert(transprob != NULL);
9015  assert(SCIPprobIsTransformed(transprob));
9016 
9017  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9018  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9019  }
9020  else
9021  {
9022  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9023  }
9024 
9025  if( nbdchgs != NULL )
9026  (*nbdchgs)++;
9027  }
9028  }
9029 
9030  return SCIP_OKAY;
9031 }
9032 
9033 /** actually performs the addition of an implication to the variable's implication arrays,
9034  * and adds the corresponding implication or variable bound to the implied variable;
9035  * if the implication is conflicting, the variable is fixed to the opposite value;
9036  * if the variable is already fixed to the given value, the implication is performed immediately;
9037  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9038  */
9039 static
9041  SCIP_VAR* var, /**< problem variable */
9042  BMS_BLKMEM* blkmem, /**< block memory */
9043  SCIP_SET* set, /**< global SCIP settings */
9044  SCIP_STAT* stat, /**< problem statistics */
9045  SCIP_PROB* transprob, /**< transformed problem */
9046  SCIP_PROB* origprob, /**< original problem */
9047  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9048  SCIP_REOPT* reopt, /**< reoptimization data structure */
9049  SCIP_LP* lp, /**< current LP data */
9050  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9051  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9052  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9053  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9054  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9055  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9056  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9057  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9058  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9059  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9060  SCIP_Bool* added /**< pointer to store whether an implication was added */
9061  )
9062 {
9063  SCIP_Bool redundant;
9064  SCIP_Bool conflict;
9065 
9066  assert(var != NULL);
9067  assert(SCIPvarIsActive(var));
9069  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9070  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9071  assert(infeasible != NULL);
9072  assert(added != NULL);
9073 
9074  /* check implication on debugging solution */
9075  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9076 
9077  *infeasible = FALSE;
9078  *added = FALSE;
9079 
9080  /* check, if the implication is redundant or infeasible */
9081  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9082  assert(!redundant || !conflict);
9083  if( redundant )
9084  return SCIP_OKAY;
9085 
9086  if( var == implvar )
9087  {
9088  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9089  * x == varfixing => x < 0 or x > 1
9090  */
9091  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9092  conflict = TRUE;
9093  else
9094  {
9095  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9096  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9097  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9098  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9099  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9100  if( !conflict )
9101  return SCIP_OKAY;
9102  }
9103  }
9104 
9105  /* check, if the variable is already fixed */
9106  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9107  {
9108  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9109  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9110  {
9111  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9112  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9113  }
9114  return SCIP_OKAY;
9115  }
9116 
9117  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9118  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9119 
9120  if( !conflict )
9121  {
9122  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9123 
9124  if( SCIPvarIsBinary(implvar) )
9125  {
9126  SCIP_VAR* vars[2];
9127  SCIP_Bool vals[2];
9128 
9129  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9130  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9131 
9132  vars[0] = var;
9133  vars[1] = implvar;
9134  vals[0] = varfixing;
9135  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9136 
9137  /* add the clique to the clique table */
9138  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9139  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9140 
9141  if( !conflict )
9142  return SCIP_OKAY;
9143  }
9144  else
9145  {
9146  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9147  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9148  SCIPvarGetName(var), varfixing,
9149  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9150  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9151  isshortcut, &conflict, added) );
9152  }
9153  }
9154  assert(!conflict || !(*added));
9155 
9156  /* on conflict, fix the variable to the opposite value */
9157  if( conflict )
9158  {
9159  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9160 
9161  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9162  * with the local bound, in this case we need to store the bound change as pending bound change
9163  */
9164  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9165  {
9166  assert(tree != NULL);
9167  assert(transprob != NULL);
9168  assert(SCIPprobIsTransformed(transprob));
9169 
9170  if( varfixing )
9171  {
9172  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9173  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9174  }
9175  else
9176  {
9177  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9178  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9179  }
9180  }
9181  else
9182  {
9183  if( varfixing )
9184  {
9185  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9186  }
9187  else
9188  {
9189  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9190  }
9191  }
9192  if( nbdchgs != NULL )
9193  (*nbdchgs)++;
9194 
9195  return SCIP_OKAY;
9196  }
9197  else if( *added )
9198  {
9199  /* issue IMPLADDED event */
9200  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9201  }
9202  else
9203  {
9204  /* the implication was redundant: the inverse is also redundant */
9205  return SCIP_OKAY;
9206  }
9207 
9208  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9209 
9210  /* check, whether implied variable is binary */
9211  if( !SCIPvarIsBinary(implvar) )
9212  {
9213  SCIP_Real lb;
9214  SCIP_Real ub;
9215 
9216  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9217  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9218  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9219  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9220  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9221  * for numerical reasons, ignore variable bounds with large absolute coefficient
9222  */
9223  lb = SCIPvarGetLbGlobal(implvar);
9224  ub = SCIPvarGetUbGlobal(implvar);
9225  if( impltype == SCIP_BOUNDTYPE_UPPER )
9226  {
9227  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9228  {
9229  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9230  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9231  }
9232  }
9233  else
9234  {
9235  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9236  {
9237  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9238  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9239  }
9240  }
9241  }
9242 
9243  return SCIP_OKAY;
9244 }
9245 
9246 /** adds transitive closure for binary implication x = a -> y = b */
9247 static
9249  SCIP_VAR* var, /**< problem variable */
9250  BMS_BLKMEM* blkmem, /**< block memory */
9251  SCIP_SET* set, /**< global SCIP settings */
9252  SCIP_STAT* stat, /**< problem statistics */
9253  SCIP_PROB* transprob, /**< transformed problem */
9254  SCIP_PROB* origprob, /**< original problem */
9255  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9256  SCIP_REOPT* reopt, /**< reoptimization data structure */
9257  SCIP_LP* lp, /**< current LP data */
9258  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9259  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9260  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9261  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9262  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9263  SCIP_Bool implvarfixing, /**< fixing b in implication */
9264  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9265  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9266  )
9267 {
9268  SCIP_VAR** implvars;
9269  SCIP_BOUNDTYPE* impltypes;
9270  SCIP_Real* implbounds;
9271  int nimpls;
9272  int i;
9273 
9274  *infeasible = FALSE;
9275 
9276  /* binary variable: implications of implvar */
9277  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9278  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9279  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9280  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9281 
9282  /* if variable has too many implications, the implication graph may become too dense */
9283  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9284 
9285  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9286  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9287  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9288  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9289  * only thing that can happen is that we add the same implication twice - this does no harm
9290  */
9291  while ( i >= 0 && !(*infeasible) )
9292  {
9293  SCIP_Bool added;
9294 
9295  assert(implvars[i] != implvar);
9296 
9297  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9298  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9299  */
9300  if( SCIPvarIsActive(implvars[i]) )
9301  {
9302  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9303  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9304  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9305  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9306  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9307  }
9308  --i;
9309  }
9310 
9311  return SCIP_OKAY;
9312 }
9313 
9314 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9315  * implication to the variable's implication list;
9316  * if the implication is conflicting, the variable is fixed to the opposite value;
9317  * if the variable is already fixed to the given value, the implication is performed immediately;
9318  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9319  */
9320 static
9322  SCIP_VAR* var, /**< problem variable */
9323  BMS_BLKMEM* blkmem, /**< block memory */
9324  SCIP_SET* set, /**< global SCIP settings */
9325  SCIP_STAT* stat, /**< problem statistics */
9326  SCIP_PROB* transprob, /**< transformed problem */
9327  SCIP_PROB* origprob, /**< original problem */
9328  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9329  SCIP_REOPT* reopt, /**< reoptimization data structure */
9330  SCIP_LP* lp, /**< current LP data */
9331  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9332  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9333  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9334  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9335  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9336  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9337  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9338  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9339  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9340  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9341  )
9342 {
9343  SCIP_Bool added;
9344 
9345  assert(var != NULL);
9346  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9347  assert(SCIPvarIsActive(var));
9348  assert(implvar != NULL);
9349  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9350  assert(infeasible != NULL);
9351 
9352  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9353  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9354  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9355 
9356  if( *infeasible || var == implvar || !transitive || !added )
9357  return SCIP_OKAY;
9358 
9359  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9360 
9361  /* add transitive closure */
9362  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9363  {
9364  SCIP_Bool implvarfixing;
9365 
9366  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9367 
9368  /* binary variable: implications of implvar */
9369  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9370  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9371 
9372  /* inverse implication */
9373  if( !(*infeasible) )
9374  {
9375  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9376  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9377  }
9378  }
9379  else
9380  {
9381  /* non-binary variable: variable lower bounds of implvar */
9382  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9383  {
9384  SCIP_VAR** vlbvars;
9385  SCIP_Real* vlbcoefs;
9386  SCIP_Real* vlbconstants;
9387  int nvlbvars;
9388  int i;
9389 
9390  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9391  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9392  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9393  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9394 
9395  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9396  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9397  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9398  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9399  * is that we add the same implication twice - this does no harm
9400  */
9401  i = nvlbvars-1;
9402  while ( i >= 0 && !(*infeasible) )
9403  {
9404  assert(vlbvars[i] != implvar);
9405  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9406 
9407  /* we have x == varfixing -> y <= b and y >= c*z + d:
9408  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9409  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9410  *
9411  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9412  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9413  * aggregation variable (the one which will stay active);
9414  *
9415  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9416  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9417  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9418  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9419  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9420  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9421  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9422  * have to explicitly check that the active variable has not a variable status
9423  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9424  */
9425  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9426  {
9427  SCIP_Real vbimplbound;
9428 
9429  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9430  if( vlbcoefs[i] >= 0.0 )
9431  {
9432  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9433  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9434  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9435  infeasible, nbdchgs, &added) );
9436  }
9437  else
9438  {
9439  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9440  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9441  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9442  infeasible, nbdchgs, &added) );
9443  }
9444  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9445  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9446  }
9447  --i;
9448  }
9449  }
9450 
9451  /* non-binary variable: variable upper bounds of implvar */
9452  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9453  {
9454  SCIP_VAR** vubvars;
9455  SCIP_Real* vubcoefs;
9456  SCIP_Real* vubconstants;
9457  int nvubvars;
9458  int i;
9459 
9460  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9461  vubvars = SCIPvboundsGetVars(implvar->vubs);
9462  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9463  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9464 
9465  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9466  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9467  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9468  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9469  * is that we add the same implication twice - this does no harm
9470  */
9471  i = nvubvars-1;
9472  while ( i >= 0 && !(*infeasible) )
9473  {
9474  assert(vubvars[i] != implvar);
9475  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9476 
9477  /* we have x == varfixing -> y >= b and y <= c*z + d:
9478  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9479  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9480  *
9481  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9482  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9483  * aggregation variable (the one which will stay active);
9484  *
9485  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9486  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9487  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9488  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9489  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9490  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9491  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9492  * have to explicitly check that the active variable has not a variable status
9493  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9494  */
9495  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9496  {
9497  SCIP_Real vbimplbound;
9498 
9499  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9500  if( vubcoefs[i] >= 0.0 )
9501  {
9502  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9503  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9504  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9505  infeasible, nbdchgs, &added) );
9506  }
9507  else
9508  {
9509  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9510  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9511  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9512  infeasible, nbdchgs, &added) );
9513  }
9514  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9515  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9516  }
9517  --i;
9518  }
9519  }
9520  }
9521 
9522  return SCIP_OKAY;
9523 }
9524 
9525 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9526  * if z is binary, the corresponding valid implication for z is also added;
9527  * improves the global bounds of the variable and the vlb variable if possible
9528  */
9530  SCIP_VAR* var, /**< problem variable */
9531  BMS_BLKMEM* blkmem, /**< block memory */
9532  SCIP_SET* set, /**< global SCIP settings */
9533  SCIP_STAT* stat, /**< problem statistics */
9534  SCIP_PROB* transprob, /**< transformed problem */
9535  SCIP_PROB* origprob, /**< original problem */
9536  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9537  SCIP_REOPT* reopt, /**< reoptimization data structure */
9538  SCIP_LP* lp, /**< current LP data */
9539  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9540  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9541  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9542  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9543  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9544  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9545  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9546  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9547  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9548  )
9549 {
9550  assert(var != NULL);
9551  assert(set != NULL);
9552  assert(var->scip == set->scip);
9553  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9554  assert(infeasible != NULL);
9555 
9556  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9557 
9558  *infeasible = FALSE;
9559  if( nbdchgs != NULL )
9560  *nbdchgs = 0;
9561 
9562  switch( SCIPvarGetStatus(var) )
9563  {
9565  assert(var->data.original.transvar != NULL);
9566  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9567  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9568  break;
9569 
9570  case SCIP_VARSTATUS_COLUMN:
9571  case SCIP_VARSTATUS_LOOSE:
9572  case SCIP_VARSTATUS_FIXED:
9573  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9574  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9575  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9576 
9577  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9578  if( SCIPsetIsZero(set, vlbcoef) )
9579  {
9580  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9581  *infeasible = TRUE;
9582  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9583  {
9584  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9585  * with the local bound, in this case we need to store the bound change as pending bound change
9586  */
9587  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9588  {
9589  assert(tree != NULL);
9590  assert(transprob != NULL);
9591  assert(SCIPprobIsTransformed(transprob));
9592 
9593  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9594  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9595  }
9596  else
9597  {
9598  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9599  }
9600 
9601  if( nbdchgs != NULL )
9602  (*nbdchgs)++;
9603  }
9604  }
9605  else if( SCIPvarIsActive(vlbvar) )
9606  {
9607  SCIP_Real xlb;
9608  SCIP_Real xub;
9609  SCIP_Real zlb;
9610  SCIP_Real zub;
9611  SCIP_Real minvlb;
9612  SCIP_Real maxvlb;
9613 
9615  assert(vlbcoef != 0.0);
9616 
9617  minvlb = -SCIPsetInfinity(set);
9618  maxvlb = SCIPsetInfinity(set);
9619 
9620  xlb = SCIPvarGetLbGlobal(var);
9621  xub = SCIPvarGetUbGlobal(var);
9622  zlb = SCIPvarGetLbGlobal(vlbvar);
9623  zub = SCIPvarGetUbGlobal(vlbvar);
9624 
9625  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9626  if( vlbcoef >= 0.0 )
9627  {
9628  SCIP_Real newzub;
9629 
9630  if( !SCIPsetIsInfinity(set, xub) )
9631  {
9632  /* x >= b*z + d -> z <= (x-d)/b */
9633  newzub = (xub - vlbconstant)/vlbcoef;
9634 
9635  /* return if the new bound is less than -infinity */
9636  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9637  return SCIP_OKAY;
9638 
9639  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9640  {
9641  *infeasible = TRUE;
9642  return SCIP_OKAY;
9643  }
9644  if( SCIPsetIsFeasLT(set, newzub, zub) )
9645  {
9646  /* bound might be adjusted due to integrality condition */
9647  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9648 
9649  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9650  * with the local bound, in this case we need to store the bound change as pending bound change
9651  */
9652  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9653  {
9654  assert(tree != NULL);
9655  assert(transprob != NULL);
9656  assert(SCIPprobIsTransformed(transprob));
9657 
9658  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9659  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9660  }
9661  else
9662  {
9663  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9664  }
9665  zub = newzub;
9666 
9667  if( nbdchgs != NULL )
9668  (*nbdchgs)++;
9669  }
9670  maxvlb = vlbcoef * zub + vlbconstant;
9671  if( !SCIPsetIsInfinity(set, -zlb) )
9672  minvlb = vlbcoef * zlb + vlbconstant;
9673  }
9674  else
9675  {
9676  if( !SCIPsetIsInfinity(set, zub) )
9677  maxvlb = vlbcoef * zub + vlbconstant;
9678  if( !SCIPsetIsInfinity(set, -zlb) )
9679  minvlb = vlbcoef * zlb + vlbconstant;
9680  }
9681  }
9682  else
9683  {
9684  SCIP_Real newzlb;
9685 
9686  if( !SCIPsetIsInfinity(set, xub) )
9687  {
9688  /* x >= b*z + d -> z >= (x-d)/b */
9689  newzlb = (xub - vlbconstant)/vlbcoef;
9690 
9691  /* return if the new bound is larger than infinity */
9692  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9693  return SCIP_OKAY;
9694 
9695  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9696  {
9697  *infeasible = TRUE;
9698  return SCIP_OKAY;
9699  }
9700  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9701  {
9702  /* bound might be adjusted due to integrality condition */
9703  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9704 
9705  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9706  * with the local bound, in this case we need to store the bound change as pending bound change
9707  */
9708  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9709  {
9710  assert(tree != NULL);
9711  assert(transprob != NULL);
9712  assert(SCIPprobIsTransformed(transprob));
9713 
9714  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9715  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9716  }
9717  else
9718  {
9719  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9720  }
9721  zlb = newzlb;
9722 
9723  if( nbdchgs != NULL )
9724  (*nbdchgs)++;
9725  }
9726  maxvlb = vlbcoef * zlb + vlbconstant;
9727  if( !SCIPsetIsInfinity(set, zub) )
9728  minvlb = vlbcoef * zub + vlbconstant;
9729  }
9730  else
9731  {
9732  if( !SCIPsetIsInfinity(set, -zlb) )
9733  maxvlb = vlbcoef * zlb + vlbconstant;
9734  if( !SCIPsetIsInfinity(set, zub) )
9735  minvlb = vlbcoef * zub + vlbconstant;
9736  }
9737  }
9738  if( maxvlb < minvlb )
9739  maxvlb = minvlb;
9740 
9741  /* adjust bounds due to integrality of variable */
9742  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9743  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9744 
9745  /* check bounds for feasibility */
9746  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9747  {
9748  *infeasible = TRUE;
9749  return SCIP_OKAY;
9750  }
9751  /* improve global lower bound of variable */
9752  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9753  {
9754  /* bound might be adjusted due to integrality condition */
9755  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9756 
9757  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9758  * with the local bound, in this case we need to store the bound change as pending bound change
9759  */
9760  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9761  {
9762  assert(tree != NULL);
9763  assert(transprob != NULL);
9764  assert(SCIPprobIsTransformed(transprob));
9765 
9766  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9767  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9768  }
9769  else
9770  {
9771  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9772  }
9773  xlb = minvlb;
9774 
9775  if( nbdchgs != NULL )
9776  (*nbdchgs)++;
9777  }
9778  minvlb = xlb;
9779 
9780  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9781  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9782  {
9783  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9784  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9785  */
9786 
9787  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9788 
9789  if( vlbcoef >= 0.0 )
9790  {
9791  vlbcoef = maxvlb - minvlb;
9792  vlbconstant = minvlb;
9793  }
9794  else
9795  {
9796  vlbcoef = minvlb - maxvlb;
9797  vlbconstant = maxvlb;
9798  }
9799  }
9800 
9801  /* add variable bound to the variable bounds list */
9802  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9803  {
9804  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9805  assert(!SCIPsetIsZero(set, vlbcoef));
9806 
9807  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9808  * list, thereby also adding the variable bound (or implication) to the other variable
9809  */
9810  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9811  {
9812  /* add corresponding implication:
9813  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9814  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9815  */
9816  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9817  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9818  infeasible, nbdchgs) );
9819  }
9820  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9821  {
9822  /* add corresponding implication:
9823  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9824  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9825  */
9826  SCIP_Real implbound;
9827  implbound = -vlbconstant/vlbcoef;
9828 
9829  /* tighten the implication bound if the variable is integer */
9830  if( SCIPvarIsIntegral(vlbvar) )
9831  {
9832  if( vlbcoef >= 0 )
9833  implbound = SCIPsetFloor(set, implbound);
9834  else
9835  implbound = SCIPsetCeil(set, implbound);
9836  }
9837  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9838  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
9839  implbound, transitive, infeasible, nbdchgs) );
9840  }
9841  else
9842  {
9843  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
9844  }
9845  }
9846  }
9847  break;
9848 
9850  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
9851  * y <= b/a * z + (d-c)/a, if a < 0
9852  */
9853  assert(var->data.aggregate.var != NULL);
9854  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9855  {
9856  /* a > 0 -> add variable lower bound */
9857  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9858  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9859  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9860  }
9861  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9862  {
9863  /* a < 0 -> add variable upper bound */
9864  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9865  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9866  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9867  }
9868  else
9869  {
9870  SCIPerrorMessage("scalar is zero in aggregation\n");
9871  return SCIP_INVALIDDATA;
9872  }
9873  break;
9874 
9876  /* nothing to do here */
9877  break;
9878 
9880  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
9881  assert(var->negatedvar != NULL);
9883  assert(var->negatedvar->negatedvar == var);
9884  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9885  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
9886  nbdchgs) );
9887  break;
9888 
9889  default:
9890  SCIPerrorMessage("unknown variable status\n");
9891  return SCIP_INVALIDDATA;
9892  }
9893 
9894  return SCIP_OKAY;
9895 }
9896 
9897 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
9898  * if z is binary, the corresponding valid implication for z is also added;
9899  * updates the global bounds of the variable and the vub variable correspondingly
9900  */
9902  SCIP_VAR* var, /**< problem variable */
9903  BMS_BLKMEM* blkmem, /**< block memory */
9904  SCIP_SET* set, /**< global SCIP settings */
9905  SCIP_STAT* stat, /**< problem statistics */
9906  SCIP_PROB* transprob, /**< transformed problem */
9907  SCIP_PROB* origprob, /**< original problem */
9908  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9909  SCIP_REOPT* reopt, /**< reoptimization data structure */
9910  SCIP_LP* lp, /**< current LP data */
9911  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9912  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9913  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9914  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
9915  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
9916  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
9917  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9918  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9919  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9920  )
9921 {
9922  assert(var != NULL);
9923  assert(set != NULL);
9924  assert(var->scip == set->scip);
9925  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
9926  assert(infeasible != NULL);
9927 
9928  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9929 
9930  *infeasible = FALSE;
9931  if( nbdchgs != NULL )
9932  *nbdchgs = 0;
9933 
9934  switch( SCIPvarGetStatus(var) )
9935  {
9937  assert(var->data.original.transvar != NULL);
9938  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9939  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
9940  break;
9941 
9942  case SCIP_VARSTATUS_COLUMN:
9943  case SCIP_VARSTATUS_LOOSE:
9944  case SCIP_VARSTATUS_FIXED:
9945  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9946  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
9947  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
9948  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
9949 
9950  /* if the vub coefficient is zero, just update the upper bound of the variable */
9951  if( SCIPsetIsZero(set, vubcoef) )
9952  {
9953  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
9954  *infeasible = TRUE;
9955  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
9956  {
9957  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9958  * with the local bound, in this case we need to store the bound change as pending bound change
9959  */
9960  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9961  {
9962  assert(tree != NULL);
9963  assert(transprob != NULL);
9964  assert(SCIPprobIsTransformed(transprob));
9965 
9966  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9967  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
9968  }
9969  else
9970  {
9971  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
9972  }
9973 
9974  if( nbdchgs != NULL )
9975  (*nbdchgs)++;
9976  }
9977  }
9978  else if( SCIPvarIsActive(vubvar) )
9979  {
9980  SCIP_Real xlb;
9981  SCIP_Real xub;
9982  SCIP_Real zlb;
9983  SCIP_Real zub;
9984  SCIP_Real minvub;
9985  SCIP_Real maxvub;
9986 
9988  assert(vubcoef != 0.0);
9989 
9990  minvub = -SCIPsetInfinity(set);
9991  maxvub = SCIPsetInfinity(set);
9992 
9993  xlb = SCIPvarGetLbGlobal(var);
9994  xub = SCIPvarGetUbGlobal(var);
9995  zlb = SCIPvarGetLbGlobal(vubvar);
9996  zub = SCIPvarGetUbGlobal(vubvar);
9997 
9998  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
9999  if( vubcoef >= 0.0 )
10000  {
10001  SCIP_Real newzlb;
10002 
10003  if( !SCIPsetIsInfinity(set, -xlb) )
10004  {
10005  /* x <= b*z + d -> z >= (x-d)/b */
10006  newzlb = (xlb - vubconstant)/vubcoef;
10007  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10008  {
10009  *infeasible = TRUE;
10010  return SCIP_OKAY;
10011  }
10012  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10013  {
10014  /* bound might be adjusted due to integrality condition */
10015  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
10016 
10017  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10018  * with the local bound, in this case we need to store the bound change as pending bound change
10019  */
10020  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10021  {
10022  assert(tree != NULL);
10023  assert(transprob != NULL);
10024  assert(SCIPprobIsTransformed(transprob));
10025 
10026  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10027  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10028  }
10029  else
10030  {
10031  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10032  }
10033  zlb = newzlb;
10034 
10035  if( nbdchgs != NULL )
10036  (*nbdchgs)++;
10037  }
10038  minvub = vubcoef * zlb + vubconstant;
10039  if( !SCIPsetIsInfinity(set, zub) )
10040  maxvub = vubcoef * zub + vubconstant;
10041  }
10042  else
10043  {
10044  if( !SCIPsetIsInfinity(set, zub) )
10045  maxvub = vubcoef * zub + vubconstant;
10046  if( !SCIPsetIsInfinity(set, -zlb) )
10047  minvub = vubcoef * zlb + vubconstant;
10048  }
10049  }
10050  else
10051  {
10052  SCIP_Real newzub;
10053 
10054  if( !SCIPsetIsInfinity(set, -xlb) )
10055  {
10056  /* x <= b*z + d -> z <= (x-d)/b */
10057  newzub = (xlb - vubconstant)/vubcoef;
10058  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10059  {
10060  *infeasible = TRUE;
10061  return SCIP_OKAY;
10062  }
10063  if( SCIPsetIsFeasLT(set, newzub, zub) )
10064  {
10065  /* bound might be adjusted due to integrality condition */
10066  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10067 
10068  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10069  * with the local bound, in this case we need to store the bound change as pending bound change
10070  */
10071  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10072  {
10073  assert(tree != NULL);
10074  assert(transprob != NULL);
10075  assert(SCIPprobIsTransformed(transprob));
10076 
10077  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10078  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10079  }
10080  else
10081  {
10082  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10083  }
10084  zub = newzub;
10085 
10086  if( nbdchgs != NULL )
10087  (*nbdchgs)++;
10088  }
10089  minvub = vubcoef * zub + vubconstant;
10090  if( !SCIPsetIsInfinity(set, -zlb) )
10091  maxvub = vubcoef * zlb + vubconstant;
10092  }
10093  else
10094  {
10095  if( !SCIPsetIsInfinity(set, zub) )
10096  minvub = vubcoef * zub + vubconstant;
10097  if( !SCIPsetIsInfinity(set, -zlb) )
10098  maxvub = vubcoef * zlb + vubconstant;
10099  }
10100 
10101  }
10102  if( minvub > maxvub )
10103  minvub = maxvub;
10104 
10105  /* adjust bounds due to integrality of vub variable */
10106  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10107  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10108 
10109  /* check bounds for feasibility */
10110  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10111  {
10112  *infeasible = TRUE;
10113  return SCIP_OKAY;
10114  }
10115  /* improve global upper bound of variable */
10116  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10117  {
10118  /* bound might be adjusted due to integrality condition */
10119  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10120 
10121  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10122  * with the local bound, in this case we need to store the bound change as pending bound change
10123  */
10124  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10125  {
10126  assert(tree != NULL);
10127  assert(transprob != NULL);
10128  assert(SCIPprobIsTransformed(transprob));
10129 
10130  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10131  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10132  }
10133  else
10134  {
10135  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10136  }
10137  xub = maxvub;
10138 
10139  if( nbdchgs != NULL )
10140  (*nbdchgs)++;
10141  }
10142  maxvub = xub;
10143 
10144  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10145  if( SCIPvarIsBinary(vubvar) )
10146  {
10147  /* b > 0: x <= (maxvub - minvub) * z + minvub
10148  * b < 0: x <= (minvub - maxvub) * z + maxvub
10149  */
10150 
10151  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10152 
10153  if( vubcoef >= 0.0 )
10154  {
10155  vubcoef = maxvub - minvub;
10156  vubconstant = minvub;
10157  }
10158  else
10159  {
10160  vubcoef = minvub - maxvub;
10161  vubconstant = maxvub;
10162  }
10163  }
10164 
10165  /* add variable bound to the variable bounds list */
10166  if( SCIPsetIsFeasLT(set, minvub, xub) )
10167  {
10168  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10169  assert(!SCIPsetIsZero(set, vubcoef));
10170 
10171  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10172  * list, thereby also adding the variable bound (or implication) to the other variable
10173  */
10174  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10175  {
10176  /* add corresponding implication:
10177  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10178  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10179  */
10180  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10181  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10182  infeasible, nbdchgs) );
10183  }
10184  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10185  {
10186  /* add corresponding implication:
10187  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10188  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10189  */
10190  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10191  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10192  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10193  }
10194  else
10195  {
10196  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10197  }
10198  }
10199  }
10200  break;
10201 
10203  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10204  * y >= b/a * z + (d-c)/a, if a < 0
10205  */
10206  assert(var->data.aggregate.var != NULL);
10207  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10208  {
10209  /* a > 0 -> add variable upper bound */
10210  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10211  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10212  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10213  }
10214  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10215  {
10216  /* a < 0 -> add variable lower bound */
10217  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10218  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10219  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10220  }
10221  else
10222  {
10223  SCIPerrorMessage("scalar is zero in aggregation\n");
10224  return SCIP_INVALIDDATA;
10225  }
10226  break;
10227 
10229  /* nothing to do here */
10230  break;
10231 
10233  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10234  assert(var->negatedvar != NULL);
10236  assert(var->negatedvar->negatedvar == var);
10237  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10238  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10239  nbdchgs) );
10240  break;
10241 
10242  default:
10243  SCIPerrorMessage("unknown variable status\n");
10244  return SCIP_INVALIDDATA;
10245  }
10246 
10247  return SCIP_OKAY;
10248 }
10249 
10250 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10251  * also adds the corresponding implication or variable bound to the implied variable;
10252  * if the implication is conflicting, the variable is fixed to the opposite value;
10253  * if the variable is already fixed to the given value, the implication is performed immediately;
10254  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10255  */
10257  SCIP_VAR* var, /**< problem variable */
10258  BMS_BLKMEM* blkmem, /**< block memory */
10259  SCIP_SET* set, /**< global SCIP settings */
10260  SCIP_STAT* stat, /**< problem statistics */
10261  SCIP_PROB* transprob, /**< transformed problem */
10262  SCIP_PROB* origprob, /**< original problem */
10263  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10264  SCIP_REOPT* reopt, /**< reoptimization data structure */
10265  SCIP_LP* lp, /**< current LP data */
10266  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10267  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10268  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10269  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10270  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10271  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10272  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10273  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10274  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10275  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10276  )
10277 {
10278  assert(var != NULL);
10279  assert(set != NULL);
10280  assert(var->scip == set->scip);
10281  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10282  assert(infeasible != NULL);
10283 
10284  *infeasible = FALSE;
10285  if( nbdchgs != NULL )
10286  *nbdchgs = 0;
10287 
10288  switch( SCIPvarGetStatus(var) )
10289  {
10291  assert(var->data.original.transvar != NULL);
10292  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10293  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10294  nbdchgs) );
10295  break;
10296 
10297  case SCIP_VARSTATUS_COLUMN:
10298  case SCIP_VARSTATUS_LOOSE:
10299  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10300  * the variable, the implication can be applied directly;
10301  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10302  */
10303  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10304  {
10305  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10306  {
10307  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10308  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10309  }
10310  }
10311  else
10312  {
10313  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10314  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10315  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10316  {
10317  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10318  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10319  }
10320  }
10321  break;
10322 
10323  case SCIP_VARSTATUS_FIXED:
10324  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10325  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10326  {
10327  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10328  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10329  }
10330  break;
10331 
10333  /* implication added for x == 1:
10334  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10335  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10336  * implication added for x == 0:
10337  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10338  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10339  *
10340  * use only binary variables z
10341  */
10342  assert(var->data.aggregate.var != NULL);
10343  if( SCIPvarIsBinary(var->data.aggregate.var) )
10344  {
10345  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10346  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10347 
10348  if( var->data.aggregate.scalar > 0 )
10349  {
10350  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10351  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10352  nbdchgs) );
10353  }
10354  else
10355  {
10356  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10357  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10358  nbdchgs) );
10359  }
10360  }
10361  break;
10362 
10364  /* nothing to do here */
10365  break;
10366 
10368  /* implication added for x == 1:
10369  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10370  * implication added for x == 0:
10371  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10372  */
10373  assert(var->negatedvar != NULL);
10375  assert(var->negatedvar->negatedvar == var);
10376  assert(SCIPvarIsBinary(var->negatedvar));
10377 
10379  {
10380  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10381  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10382  }
10383  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10384  else
10385  {
10386  /* if the implied variable is of binary type exchange the variables */
10387  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10388  {
10389  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10390  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10391  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10392  infeasible, nbdchgs) );
10393  }
10394  else
10395  {
10396  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10397  * implication as variable bounds
10398  */
10399 
10400  /* add variable lower bound on the negation of var */
10401  if( varfixing )
10402  {
10403  /* (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
10404  * as variable lower bound
10405  */
10406  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10407  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10408  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10409  }
10410  else
10411  {
10412  /* (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
10413  * as variable upper bound
10414  */
10415  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10416  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10417  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10418  }
10419 
10420  /* add variable bound on implvar */
10421  if( impltype == SCIP_BOUNDTYPE_UPPER )
10422  {
10423  /* (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
10424  * as variable upper bound
10425  */
10426  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10427  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10428  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10429  }
10430  else
10431  {
10432  /* (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
10433  * as variable upper bound
10434  */
10435  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10436  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10437  transitive, infeasible, nbdchgs) );
10438  }
10439  }
10440  }
10441  break;
10442 
10443  default:
10444  SCIPerrorMessage("unknown variable status\n");
10445  return SCIP_INVALIDDATA;
10446  }
10447 
10448  return SCIP_OKAY;
10449 }
10450 
10451 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10452  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10453  * both variables must be active, variable x must be binary
10454  */
10456  SCIP_VAR* var, /**< problem variable x */
10457  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10458  SCIP_VAR* implvar, /**< variable y to search for */
10459  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10460  )
10461 {
10462  assert(var != NULL);
10463  assert(implvar != NULL);
10464  assert(SCIPvarIsActive(var));
10465  assert(SCIPvarIsActive(implvar));
10466  assert(SCIPvarIsBinary(var));
10467 
10468  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10469 }
10470 
10471 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10472  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10473  * both variables must be active binary variables
10474  */
10476  SCIP_VAR* var, /**< problem variable x */
10477  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10478  SCIP_VAR* implvar, /**< variable y to search for */
10479  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10480  )
10481 {
10482  assert(SCIPvarIsBinary(implvar));
10483 
10484  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10485 }
10486 
10487 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10489  SCIP_VAR* var, /**< problem variable */
10490  BMS_BLKMEM* blkmem, /**< block memory */
10491  SCIP_SET* set, /**< global SCIP settings */
10492  SCIP_STAT* stat, /**< problem statistics */
10493  SCIP_PROB* transprob, /**< transformed problem */
10494  SCIP_PROB* origprob, /**< original problem */
10495  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10496  SCIP_REOPT* reopt, /**< reoptimization data structure */
10497  SCIP_LP* lp, /**< current LP data */
10498  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10499  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10500  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10501  SCIP_Bool value, /**< value to fix variable to */
10502  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10503  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10504  )
10505 {
10506  assert(var != NULL);
10507  assert(set != NULL);
10508  assert(var->scip == set->scip);
10509  assert(infeasible != NULL);
10510 
10511  *infeasible = FALSE;
10512 
10513  if( value == FALSE )
10514  {
10515  if( var->glbdom.lb > 0.5 )
10516  *infeasible = TRUE;
10517  else if( var->glbdom.ub > 0.5 )
10518  {
10519  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10520  * with the local bound, in this case we need to store the bound change as pending bound change
10521  */
10522  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10523  {
10524  assert(tree != NULL);
10525  assert(transprob != NULL);
10526  assert(SCIPprobIsTransformed(transprob));
10527 
10528  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10529  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10530  }
10531  else
10532  {
10533  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10534  }
10535 
10536  if( nbdchgs != NULL )
10537  (*nbdchgs)++;
10538  }
10539  }
10540  else
10541  {
10542  if( var->glbdom.ub < 0.5 )
10543  *infeasible = TRUE;
10544  else if( var->glbdom.lb < 0.5 )
10545  {
10546  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10547  * with the local bound, in this case we need to store the bound change as pending bound change
10548  */
10549  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10550  {
10551  assert(tree != NULL);
10552  assert(transprob != NULL);
10553  assert(SCIPprobIsTransformed(transprob));
10554 
10555  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10556  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10557  }
10558  else
10559  {
10560  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10561  }
10562 
10563  if( nbdchgs != NULL )
10564  (*nbdchgs)++;
10565  }
10566  }
10567 
10568  /* during presolving, the variable should have been removed immediately from all its cliques */
10569  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10570 
10571  return SCIP_OKAY;
10572 }
10573 
10574 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10575  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10576  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10577  * the opposite of the value they take in the clique
10578  */
10580  SCIP_VAR* var, /**< problem variable */
10581  BMS_BLKMEM* blkmem, /**< block memory */
10582  SCIP_SET* set, /**< global SCIP settings */
10583  SCIP_STAT* stat, /**< problem statistics */
10584  SCIP_PROB* transprob, /**< transformed problem */
10585  SCIP_PROB* origprob, /**< original problem */
10586  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10587  SCIP_REOPT* reopt, /**< reoptimization data structure */
10588  SCIP_LP* lp, /**< current LP data */
10589  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10590  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10591  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10592  SCIP_Bool value, /**< value of the variable in the clique */
10593  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10594  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10595  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10596  )
10597 {
10598  assert(var != NULL);
10599  assert(set != NULL);
10600  assert(var->scip == set->scip);
10601  assert(SCIPvarIsBinary(var));
10602  assert(infeasible != NULL);
10603 
10604  *infeasible = FALSE;
10605 
10606  /* get corresponding active problem variable */
10607  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10612  assert(SCIPvarIsBinary(var));
10613 
10614  /* only column and loose variables may be member of a clique */
10616  {
10617  SCIP_Bool doubleentry;
10618  SCIP_Bool oppositeentry;
10619 
10620  /* add variable to clique */
10621  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10622 
10623  /* add clique to variable's clique list */
10624  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10625 
10626  /* check consistency of cliquelist */
10627  SCIPcliquelistCheck(var->cliquelist, var);
10628 
10629  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10630  if( doubleentry )
10631  {
10632  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10633  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10634  }
10635 
10636  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10637  * to the opposite of the value they take in the clique
10638  */
10639  if( oppositeentry )
10640  {
10641  SCIP_VAR** vars;
10642  SCIP_Bool* values;
10643  int nvars;
10644  int i;
10645 
10646  nvars = SCIPcliqueGetNVars(clique);
10647  vars = SCIPcliqueGetVars(clique);
10648  values = SCIPcliqueGetValues(clique);
10649  for( i = 0; i < nvars && !(*infeasible); ++i )
10650  {
10651  if( vars[i] == var )
10652  continue;
10653 
10654  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10655  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10656  }
10657  }
10658  }
10659 
10660  return SCIP_OKAY;
10661 }
10662 
10663 /** adds a filled clique to the cliquelists of all corresponding variables */
10665  SCIP_VAR** vars, /**< problem variables */
10666  SCIP_Bool* values, /**< values of the variables in the clique */
10667  int nvars, /**< number of problem variables */
10668  BMS_BLKMEM* blkmem, /**< block memory */
10669  SCIP_SET* set, /**< global SCIP settings */
10670  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10671  )
10672 {
10673  SCIP_VAR* var;
10674  int v;
10675 
10676  assert(vars != NULL);
10677  assert(values != NULL);
10678  assert(nvars > 0);
10679  assert(set != NULL);
10680  assert(blkmem != NULL);
10681  assert(clique != NULL);
10682 
10683  for( v = nvars - 1; v >= 0; --v )
10684  {
10685  var = vars[v];
10686  assert(SCIPvarIsBinary(var));
10688 
10689  /* add clique to variable's clique list */
10690  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10691 
10692  /* check consistency of cliquelist */
10693  SCIPcliquelistCheck(var->cliquelist, var);
10694  }
10695 
10696  return SCIP_OKAY;
10697 }
10698 
10699 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10700  * itself
10701  */
10703  SCIP_VAR* var, /**< problem variable */
10704  BMS_BLKMEM* blkmem, /**< block memory */
10705  SCIP_SET* set, /**< global SCIP settings */
10706  SCIP_Bool value, /**< value of the variable in the clique */
10707  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10708  )
10709 {
10710  assert(var != NULL);
10711  assert(SCIPvarIsBinary(var));
10713 
10714  /* add clique to variable's clique list */
10715  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10716 
10717  return SCIP_OKAY;
10718 }
10719 
10720 
10721 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10722  * itself
10723  */
10725  SCIP_VAR* var, /**< problem variable */
10726  BMS_BLKMEM* blkmem, /**< block memory */
10727  SCIP_Bool value, /**< value of the variable in the clique */
10728  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10729  )
10730 {
10731  assert(var != NULL);
10732  assert(SCIPvarIsBinary(var));
10733 
10734  /* delete clique from variable's clique list */
10735  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10736 
10737  return SCIP_OKAY;
10738 }
10739 
10740 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10742  SCIP_VAR* var, /**< problem variable */
10743  BMS_BLKMEM* blkmem, /**< block memory */
10744  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10745  SCIP_Bool value, /**< value of the variable in the clique */
10746  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10747  )
10748 {
10749  assert(var != NULL);
10750  assert(SCIPvarIsBinary(var));
10751 
10752  /* get corresponding active problem variable */
10753  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10758  assert(SCIPvarIsBinary(var));
10759 
10760  /* only column and loose variables may be member of a clique */
10762  {
10763  /* delete clique from variable's clique list */
10764  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10765 
10766  /* delete variable from clique */
10767  SCIPcliqueDelVar(clique, cliquetable, var, value);
10768 
10769  /* check consistency of cliquelist */
10770  SCIPcliquelistCheck(var->cliquelist, var);
10771  }
10772 
10773  return SCIP_OKAY;
10774 }
10775 
10776 /** returns whether there is a clique that contains both given variable/value pairs;
10777  * the variables must be active binary variables;
10778  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10779  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10780  *
10781  * @note a variable with it's negated variable are NOT! in a clique
10782  * @note a variable with itself are in a clique
10783  */
10785  SCIP_VAR* var1, /**< first variable */
10786  SCIP_Bool value1, /**< value of first variable */
10787  SCIP_VAR* var2, /**< second variable */
10788  SCIP_Bool value2, /**< value of second variable */
10789  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10790  )
10791 {
10792  assert(var1 != NULL);
10793  assert(var2 != NULL);
10794  assert(SCIPvarIsActive(var1));
10795  assert(SCIPvarIsActive(var2));
10796  assert(SCIPvarIsBinary(var1));
10797  assert(SCIPvarIsBinary(var2));
10798 
10799  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10800  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10801 }
10802 
10803 /** actually changes the branch factor of the variable and of all parent variables */
10804 static
10806  SCIP_VAR* var, /**< problem variable */
10807  SCIP_SET* set, /**< global SCIP settings */
10808  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10809  )
10810 {
10811  SCIP_VAR* parentvar;
10812  SCIP_Real eps;
10813  int i;
10814 
10815  assert(var != NULL);
10816  assert(set != NULL);
10817  assert(var->scip == set->scip);
10818 
10819  /* only use positive values */
10820  eps = SCIPsetEpsilon(set);
10821  branchfactor = MAX(branchfactor, eps);
10822 
10823  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10824 
10825  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10826  return SCIP_OKAY;
10827 
10828  /* change the branch factor */
10829  var->branchfactor = branchfactor;
10830 
10831  /* process parent variables */
10832  for( i = 0; i < var->nparentvars; ++i )
10833  {
10834  parentvar = var->parentvars[i];
10835  assert(parentvar != NULL);
10836 
10837  switch( SCIPvarGetStatus(parentvar) )
10838  {
10840  /* do not change priorities across the border between transformed and original problem */
10841  break;
10842 
10843  case SCIP_VARSTATUS_COLUMN:
10844  case SCIP_VARSTATUS_LOOSE:
10845  case SCIP_VARSTATUS_FIXED:
10847  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10848  SCIPABORT();
10849  return SCIP_INVALIDDATA; /*lint !e527*/
10850 
10853  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
10854  break;
10855 
10856  default:
10857  SCIPerrorMessage("unknown variable status\n");
10858  SCIPABORT();
10859  return SCIP_ERROR; /*lint !e527*/
10860  }
10861  }
10862 
10863  return SCIP_OKAY;
10864 }
10865 
10866 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
10867  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
10868  */
10870  SCIP_VAR* var, /**< problem variable */
10871  SCIP_SET* set, /**< global SCIP settings */
10872  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10873  )
10874 {
10875  int v;
10876 
10877  assert(var != NULL);
10878  assert(set != NULL);
10879  assert(var->scip == set->scip);
10880  assert(branchfactor >= 0.0);
10881 
10882  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
10883 
10884  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
10885  return SCIP_OKAY;
10886 
10887  /* change priorities of attached variables */
10888  switch( SCIPvarGetStatus(var) )
10889  {
10891  if( var->data.original.transvar != NULL )
10892  {
10893  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
10894  }
10895  else
10896  {
10897  assert(set->stage == SCIP_STAGE_PROBLEM);
10898  var->branchfactor = branchfactor;
10899  }
10900  break;
10901 
10902  case SCIP_VARSTATUS_COLUMN:
10903  case SCIP_VARSTATUS_LOOSE:
10904  case SCIP_VARSTATUS_FIXED:
10905  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
10906  break;
10907 
10909  assert(var->data.aggregate.var != NULL);
10910  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
10911  break;
10912 
10914  assert(!var->donotmultaggr);
10915  for( v = 0; v < var->data.multaggr.nvars; ++v )
10916  {
10917  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
10918  }
10919  break;
10920 
10922  assert(var->negatedvar != NULL);
10924  assert(var->negatedvar->negatedvar == var);
10925  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
10926  break;
10927 
10928  default:
10929  SCIPerrorMessage("unknown variable status\n");
10930  SCIPABORT();
10931  return SCIP_ERROR; /*lint !e527*/
10932  }
10933 
10934  return SCIP_OKAY;
10935 }
10936 
10937 /** actually changes the branch priority of the variable and of all parent variables */
10938 static
10940  SCIP_VAR* var, /**< problem variable */
10941  int branchpriority /**< branching priority of the variable */
10942  )
10943 {
10944  SCIP_VAR* parentvar;
10945  int i;
10946 
10947  assert(var != NULL);
10948 
10949  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
10950  var->name, var->branchpriority, branchpriority);
10951 
10952  if( branchpriority == var->branchpriority )
10953  return SCIP_OKAY;
10954 
10955  /* change the branch priority */
10956  var->branchpriority = branchpriority;
10957 
10958  /* process parent variables */
10959  for( i = 0; i < var->nparentvars; ++i )
10960  {
10961  parentvar = var->parentvars[i];
10962  assert(parentvar != NULL);
10963 
10964  switch( SCIPvarGetStatus(parentvar) )
10965  {
10967  /* do not change priorities across the border between transformed and original problem */
10968  break;
10969 
10970  case SCIP_VARSTATUS_COLUMN:
10971  case SCIP_VARSTATUS_LOOSE:
10972  case SCIP_VARSTATUS_FIXED:
10974  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10975  SCIPABORT();
10976  return SCIP_INVALIDDATA; /*lint !e527*/
10977 
10980  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
10981  break;
10982 
10983  default:
10984  SCIPerrorMessage("unknown variable status\n");
10985  return SCIP_ERROR;
10986  }
10987  }
10988 
10989  return SCIP_OKAY;
10990 }
10991 
10992 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
10993  * with lower priority in selection of branching variable
10994  */
10996  SCIP_VAR* var, /**< problem variable */
10997  int branchpriority /**< branching priority of the variable */
10998  )
10999 {
11000  int v;
11001 
11002  assert(var != NULL);
11003 
11004  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11005 
11006  if( var->branchpriority == branchpriority )
11007  return SCIP_OKAY;
11008 
11009  /* change priorities of attached variables */
11010  switch( SCIPvarGetStatus(var) )
11011  {
11013  if( var->data.original.transvar != NULL )
11014  {
11015  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11016  }
11017  else
11018  var->branchpriority = branchpriority;
11019  break;
11020 
11021  case SCIP_VARSTATUS_COLUMN:
11022  case SCIP_VARSTATUS_LOOSE:
11023  case SCIP_VARSTATUS_FIXED:
11024  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11025  break;
11026 
11028  assert(var->data.aggregate.var != NULL);
11029  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11030  break;
11031 
11033  assert(!var->donotmultaggr);
11034  for( v = 0; v < var->data.multaggr.nvars; ++v )
11035  {
11036  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11037  }
11038  break;
11039 
11041  assert(var->negatedvar != NULL);
11043  assert(var->negatedvar->negatedvar == var);
11044  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11045  break;
11046 
11047  default:
11048  SCIPerrorMessage("unknown variable status\n");
11049  SCIPABORT();
11050  return SCIP_ERROR; /*lint !e527*/
11051  }
11052 
11053  return SCIP_OKAY;
11054 }
11055 
11056 /** actually changes the branch direction of the variable and of all parent variables */
11057 static
11059  SCIP_VAR* var, /**< problem variable */
11060  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11061  )
11062 {
11063  SCIP_VAR* parentvar;
11064  int i;
11065 
11066  assert(var != NULL);
11067 
11068  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11069  var->name, var->branchdirection, branchdirection);
11070 
11071  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11072  return SCIP_OKAY;
11073 
11074  /* change the branch direction */
11075  var->branchdirection = branchdirection; /*lint !e641*/
11076 
11077  /* process parent variables */
11078  for( i = 0; i < var->nparentvars; ++i )
11079  {
11080  parentvar = var->parentvars[i];
11081  assert(parentvar != NULL);
11082 
11083  switch( SCIPvarGetStatus(parentvar) )
11084  {
11086  /* do not change directions across the border between transformed and original problem */
11087  break;
11088 
11089  case SCIP_VARSTATUS_COLUMN:
11090  case SCIP_VARSTATUS_LOOSE:
11091  case SCIP_VARSTATUS_FIXED:
11093  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11094  SCIPABORT();
11095  return SCIP_INVALIDDATA; /*lint !e527*/
11096 
11098  if( parentvar->data.aggregate.scalar > 0.0 )
11099  {
11100  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11101  }
11102  else
11103  {
11104  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11105  }
11106  break;
11107 
11109  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11110  break;
11111 
11112  default:
11113  SCIPerrorMessage("unknown variable status\n");
11114  SCIPABORT();
11115  return SCIP_ERROR; /*lint !e527*/
11116  }
11117  }
11118 
11119  return SCIP_OKAY;
11120 }
11121 
11122 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11123  * with lower direction in selection of branching variable
11124  */
11126  SCIP_VAR* var, /**< problem variable */
11127  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11128  )
11129 {
11130  int v;
11131 
11132  assert(var != NULL);
11133 
11134  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11135 
11136  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11137  return SCIP_OKAY;
11138 
11139  /* change directions of attached variables */
11140  switch( SCIPvarGetStatus(var) )
11141  {
11143  if( var->data.original.transvar != NULL )
11144  {
11145  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11146  }
11147  else
11148  var->branchdirection = branchdirection; /*lint !e641*/
11149  break;
11150 
11151  case SCIP_VARSTATUS_COLUMN:
11152  case SCIP_VARSTATUS_LOOSE:
11153  case SCIP_VARSTATUS_FIXED:
11154  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11155  break;
11156 
11158  assert(var->data.aggregate.var != NULL);
11159  if( var->data.aggregate.scalar > 0.0 )
11160  {
11161  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11162  }
11163  else
11164  {
11166  }
11167  break;
11168 
11170  assert(!var->donotmultaggr);
11171  for( v = 0; v < var->data.multaggr.nvars; ++v )
11172  {
11173  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11174  assert(var->data.multaggr.vars[v] != NULL);
11176  {
11177  if( var->data.multaggr.scalars[v] > 0.0 )
11178  {
11179  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11180  }
11181  else
11182  {
11184  }
11185  }
11186  }
11187  break;
11188 
11190  assert(var->negatedvar != NULL);
11192  assert(var->negatedvar->negatedvar == var);
11194  break;
11195 
11196  default:
11197  SCIPerrorMessage("unknown variable status\n");
11198  SCIPABORT();
11199  return SCIP_ERROR; /*lint !e527*/
11200  }
11201 
11202  return SCIP_OKAY;
11203 }
11204 
11205 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11206  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11207  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11208  * are equal, which means both variables are equal
11209  */
11211  SCIP_VAR* var1, /**< first problem variable */
11212  SCIP_VAR* var2 /**< second problem variable */
11213  )
11214 {
11215  assert(var1 != NULL);
11216  assert(var2 != NULL);
11219 
11221  var1 = SCIPvarGetNegatedVar(var1);
11223  var2 = SCIPvarGetNegatedVar(var2);
11224 
11225  assert(var1 != NULL);
11226  assert(var2 != NULL);
11227 
11228  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11229  return -1;
11230  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11231  return +1;
11232 
11233  assert(var1 == var2);
11234  return 0;
11235 }
11236 
11237 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11238  * variables are handled as the same variables
11239  */
11240 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11242  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11243 }
11244 
11245 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11246  * variable index; returns 0 if both indices are equal, which means both variables are equal
11247  */
11248 int SCIPvarCompare(
11249  SCIP_VAR* var1, /**< first problem variable */
11250  SCIP_VAR* var2 /**< second problem variable */
11251  )
11252 {
11253  assert(var1 != NULL);
11254  assert(var2 != NULL);
11255 
11256  if( var1->index < var2->index )
11257  return -1;
11258  else if( var1->index > var2->index )
11259  return +1;
11260  else
11261  {
11262  assert(var1 == var2);
11263  return 0;
11264  }
11265 }
11266 
11267 /** comparison method for sorting variables by non-decreasing index */
11268 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11270  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11271 }
11272 
11273 /** comparison method for sorting variables by non-decreasing objective coefficient */
11274 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11276  SCIP_Real obj1;
11277  SCIP_Real obj2;
11278 
11279  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11280  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11281 
11282  if( obj1 < obj2 )
11283  return -1;
11284  else if( obj1 > obj2 )
11285  return +1;
11286  else
11287  return 0;
11288 }
11289 
11290 /** hash key retrieval function for variables */
11291 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11292 { /*lint --e{715}*/
11293  return elem;
11294 }
11295 
11296 /** returns TRUE iff the indices of both variables are equal */
11297 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11298 { /*lint --e{715}*/
11299  if( key1 == key2 )
11300  return TRUE;
11301  return FALSE;
11302 }
11303 
11304 /** returns the hash value of the key */
11305 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11306 { /*lint --e{715}*/
11307  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11308  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11309 }
11310 
11311 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11313  SCIP_SET* set, /**< global SCIP settings */
11314  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11315  * variables, if enough slots exist
11316  */
11317  int* nvars, /**< number of given variables, and as output number of active variables,
11318  * if enough slots exist
11319  */
11320  int varssize, /**< available slots in vars array */
11321  int* requiredsize /**< pointer to store the required array size for the active variables */
11322  )
11323 {
11324  SCIP_VAR** activevars;
11325  int nactivevars;
11326  int activevarssize;
11327 
11328  SCIP_VAR* var;
11329  int v;
11330 
11331  SCIP_VAR** tmpvars;
11332  SCIP_VAR** multvars;
11333  int tmpvarssize;
11334  int ntmpvars;
11335  int noldtmpvars;
11336  int nmultvars;
11337 
11338  assert(set != NULL);
11339  assert(nvars != NULL);
11340  assert(vars != NULL || *nvars == 0);
11341  assert(varssize >= *nvars);
11342  assert(requiredsize != NULL);
11343 
11344  *requiredsize = 0;
11345 
11346  if( *nvars == 0 )
11347  return SCIP_OKAY;
11348 
11349  nactivevars = 0;
11350  activevarssize = *nvars;
11351  ntmpvars = *nvars;
11352  tmpvarssize = *nvars;
11353 
11354  /* temporary memory */
11355  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11356  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11357 
11358  noldtmpvars = ntmpvars;
11359 
11360  /* sort all variables to combine equal variables easily */
11361  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11362  for( v = ntmpvars - 1; v > 0; --v )
11363  {
11364  /* combine same variables */
11365  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11366  {
11367  --ntmpvars;
11368  tmpvars[v] = tmpvars[ntmpvars];
11369  }
11370  }
11371  /* sort all variables again to combine equal variables later on */
11372  if( noldtmpvars > ntmpvars )
11373  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11374 
11375  /* collect for each variable the representation in active variables */
11376  while( ntmpvars >= 1 )
11377  {
11378  --ntmpvars;
11379  var = tmpvars[ntmpvars];
11380  assert( var != NULL );
11381 
11382  switch( SCIPvarGetStatus(var) )
11383  {
11385  if( var->data.original.transvar == NULL )
11386  {
11387  SCIPerrorMessage("original variable has no transformed variable attached\n");
11388  SCIPABORT();
11389  return SCIP_INVALIDDATA; /*lint !e527*/
11390  }
11391  tmpvars[ntmpvars] = var->data.original.transvar;
11392  ++ntmpvars;
11393  break;
11394 
11396  tmpvars[ntmpvars] = var->data.aggregate.var;
11397  ++ntmpvars;
11398  break;
11399 
11401  tmpvars[ntmpvars] = var->negatedvar;
11402  ++ntmpvars;
11403  break;
11404 
11405  case SCIP_VARSTATUS_LOOSE:
11406  case SCIP_VARSTATUS_COLUMN:
11407  /* check for space in temporary memory */
11408  if( nactivevars >= activevarssize )
11409  {
11410  activevarssize *= 2;
11411  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11412  assert(nactivevars < activevarssize);
11413  }
11414  activevars[nactivevars] = var;
11415  nactivevars++;
11416  break;
11417 
11419  /* x = a_1*y_1 + ... + a_n*y_n + c */
11420  nmultvars = var->data.multaggr.nvars;
11421  multvars = var->data.multaggr.vars;
11422 
11423  /* check for space in temporary memory */
11424  if( nmultvars + ntmpvars > tmpvarssize )
11425  {
11426  while( nmultvars + ntmpvars > tmpvarssize )
11427  tmpvarssize *= 2;
11428  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11429  assert(nmultvars + ntmpvars <= tmpvarssize);
11430  }
11431 
11432  /* copy all multi-aggregation variables into our working array */
11433  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11434 
11435  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11436  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11437 
11438  ntmpvars += nmultvars;
11439  noldtmpvars = ntmpvars;
11440 
11441  /* sort all variables to combine equal variables easily */
11442  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11443  for( v = ntmpvars - 1; v > 0; --v )
11444  {
11445  /* combine same variables */
11446  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11447  {
11448  --ntmpvars;
11449  tmpvars[v] = tmpvars[ntmpvars];
11450  }
11451  }
11452  /* sort all variables again to combine equal variables later on */
11453  if( noldtmpvars > ntmpvars )
11454  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11455 
11456  break;
11457 
11458  case SCIP_VARSTATUS_FIXED:
11459  /* no need for memorizing fixed variables */
11460  break;
11461 
11462  default:
11463  SCIPerrorMessage("unknown variable status\n");
11464  SCIPABORT();
11465  return SCIP_INVALIDDATA; /*lint !e527*/
11466  }
11467  }
11468 
11469  /* sort variable array by variable index */
11470  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11471 
11472  /* eliminate duplicates and count required size */
11473  v = nactivevars - 1;
11474  while( v > 0 )
11475  {
11476  /* combine both variable since they are the same */
11477  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11478  {
11479  --nactivevars;
11480  activevars[v] = activevars[nactivevars];
11481  }
11482  --v;
11483  }
11484  *requiredsize = nactivevars;
11485 
11486  if( varssize >= *requiredsize )
11487  {
11488  assert(vars != NULL);
11489 
11490  *nvars = *requiredsize;
11491  BMScopyMemoryArray(vars, activevars, nactivevars);
11492  }
11493 
11494  SCIPsetFreeBufferArray(set, &tmpvars);
11495  SCIPsetFreeBufferArray(set, &activevars);
11496 
11497  return SCIP_OKAY;
11498 }
11499 
11500 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11501  * @note the content of the given array will/might change
11502  */
11503 void SCIPvarsGetProbvar(
11504  SCIP_VAR** vars, /**< array of problem variables */
11505  int nvars /**< number of variables */
11506  )
11507 {
11508  int v;
11509 
11510  assert(vars != NULL || nvars == 0);
11511 
11512  for( v = nvars - 1; v >= 0; --v )
11513  {
11514  assert(vars != NULL);
11515  assert(vars[v] != NULL);
11516 
11517  vars[v] = SCIPvarGetProbvar(vars[v]);
11518  assert(vars[v] != NULL);
11519  }
11520 }
11521 
11522 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11524  SCIP_VAR* var /**< problem variable */
11525  )
11526 {
11527  SCIP_VAR* retvar;
11528 
11529  assert(var != NULL);
11530 
11531  retvar = var;
11532 
11533  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11534 
11535  while( TRUE ) /*lint !e716 */
11536  {
11537  assert(retvar != NULL);
11538 
11539  switch( SCIPvarGetStatus(retvar) )
11540  {
11542  if( retvar->data.original.transvar == NULL )
11543  {
11544  SCIPerrorMessage("original variable has no transformed variable attached\n");
11545  SCIPABORT();
11546  return NULL; /*lint !e527 */
11547  }
11548  retvar = retvar->data.original.transvar;
11549  break;
11550 
11551  case SCIP_VARSTATUS_LOOSE:
11552  case SCIP_VARSTATUS_COLUMN:
11553  case SCIP_VARSTATUS_FIXED:
11554  return retvar;
11555 
11557  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11558  if ( retvar->data.multaggr.nvars == 1 )
11559  retvar = retvar->data.multaggr.vars[0];
11560  else
11561  return retvar;
11562  break;
11563 
11565  retvar = retvar->data.aggregate.var;
11566  break;
11567 
11569  retvar = retvar->negatedvar;
11570  break;
11571 
11572  default:
11573  SCIPerrorMessage("unknown variable status\n");
11574  SCIPABORT();
11575  return NULL; /*lint !e527*/
11576  }
11577  }
11578 }
11579 
11580 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11581  * negation status of each variable
11582  */
11584  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11585  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11586  int nvars /**< number of variables and values in vars and negated array */
11587  )
11588 {
11589  SCIP_VAR** var;
11590  SCIP_Bool* negated;
11591  int v;
11592 
11593  assert(vars != NULL);
11594  assert(*vars != NULL || nvars == 0);
11595  assert(negatedarr != NULL);
11596  assert(*negatedarr != NULL || nvars == 0);
11597 
11598  for( v = nvars - 1; v >= 0; --v )
11599  {
11600  var = &((*vars)[v]);
11601  negated = &((*negatedarr)[v]);
11602 
11603  /* get problem variable */
11604  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11605  }
11606 
11607  return SCIP_OKAY;
11608 }
11609 
11610 
11611 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11612  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11613  * FALSE is used)
11614  */
11616  SCIP_VAR** var, /**< pointer to binary problem variable */
11617  SCIP_Bool* negated /**< pointer to update the negation status */
11618  )
11619 {
11621 #ifndef NDEBUG
11622  SCIP_Real constant = 0.0;
11623  SCIP_Bool orignegated;
11624 #endif
11625 
11626  assert(var != NULL);
11627  assert(*var != NULL);
11628  assert(negated != NULL);
11629  assert(SCIPvarIsBinary(*var));
11630 
11631 #ifndef NDEBUG
11632  orignegated = *negated;
11633 #endif
11634 
11635  while( !active && *var != NULL )
11636  {
11637  switch( SCIPvarGetStatus(*var) )
11638  {
11640  if( (*var)->data.original.transvar == NULL )
11641  return SCIP_OKAY;
11642  *var = (*var)->data.original.transvar;
11643  break;
11644 
11645  case SCIP_VARSTATUS_LOOSE:
11646  case SCIP_VARSTATUS_COLUMN:
11647  case SCIP_VARSTATUS_FIXED:
11648  active = TRUE;
11649  break;
11650 
11652  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11653  if ( (*var)->data.multaggr.nvars == 1 )
11654  {
11655  assert( (*var)->data.multaggr.vars != NULL );
11656  assert( (*var)->data.multaggr.scalars != NULL );
11657  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11658  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11659 
11660  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11661  * another variable which needs to be fixed
11662  *
11663  * e.g. x = y - 1 => (x = 0 && y = 1)
11664  * e.g. x = y + 1 => (x = 1 && y = 0)
11665  *
11666  * is this special case we need to return the muti-aggregation
11667  */
11668  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)) )
11669  {
11670  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11671  }
11672  else
11673  {
11674  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11675  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11676  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11677  * we will return the aggregated variable;
11678  */
11679  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11680  {
11681  active = TRUE;
11682  break;
11683  }
11684 
11685  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11686  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11687  * so if this is the case, we will return the aggregated variable
11688  */
11689  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11690  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11691  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11692 
11693  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11694  {
11695  active = TRUE;
11696  break;
11697  }
11698 
11699  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11700 
11701  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11702  {
11703  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11704  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11705  * variable itself is multi-aggregated again?
11706  */
11707  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11708  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11709  SCIPvarGetNLocksUp((*var)->data.multaggr.vars[0]) > 0) : TRUE);
11710  }
11711  else
11712  {
11713  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11714 #ifndef NDEBUG
11715  constant += (*negated) != orignegated ? -1.0 : 1.0;
11716 #endif
11717 
11718  *negated = !(*negated);
11719  }
11720  *var = (*var)->data.multaggr.vars[0];
11721  break;
11722  }
11723  }
11724  active = TRUE;
11725  break;
11726 
11727  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11728  assert((*var)->data.aggregate.var != NULL);
11729  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11730  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11731 #ifndef NDEBUG
11732  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11733 #endif
11734 
11735  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11736  *var = (*var)->data.aggregate.var;
11737  break;
11738 
11739  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11740  assert((*var)->negatedvar != NULL);
11741 #ifndef NDEBUG
11742  constant += (*negated) != orignegated ? -1.0 : 1.0;
11743 #endif
11744 
11745  *negated = !(*negated);
11746  *var = (*var)->negatedvar;
11747  break;
11748 
11749  default:
11750  SCIPerrorMessage("unknown variable status\n");
11751  return SCIP_INVALIDDATA;
11752  }
11753  }
11754  assert(active == (*var != NULL));
11755 
11756  if( active )
11757  {
11758  assert(SCIPvarIsBinary(*var));
11759  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11760  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11761 
11762  return SCIP_OKAY;
11763  }
11764  else
11765  {
11766  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11767  return SCIP_INVALIDDATA;
11768  }
11769 }
11770 
11771 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11772  * values
11773  */
11775  SCIP_VAR** var, /**< pointer to problem variable */
11776  SCIP_Real* bound, /**< pointer to bound value to transform */
11777  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11778  )
11779 {
11780  assert(var != NULL);
11781  assert(*var != NULL);
11782  assert(bound != NULL);
11783  assert(boundtype != NULL);
11784 
11785  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11786 
11787  switch( SCIPvarGetStatus(*var) )
11788  {
11790  if( (*var)->data.original.transvar == NULL )
11791  {
11792  SCIPerrorMessage("original variable has no transformed variable attached\n");
11793  return SCIP_INVALIDDATA;
11794  }
11795  *var = (*var)->data.original.transvar;
11796  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11797  break;
11798 
11799  case SCIP_VARSTATUS_LOOSE:
11800  case SCIP_VARSTATUS_COLUMN:
11801  case SCIP_VARSTATUS_FIXED:
11802  break;
11803 
11805  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11806  if ( (*var)->data.multaggr.nvars == 1 )
11807  {
11808  assert( (*var)->data.multaggr.vars != NULL );
11809  assert( (*var)->data.multaggr.scalars != NULL );
11810  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11811 
11812  (*bound) /= (*var)->data.multaggr.scalars[0];
11813  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11814  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11815  {
11816  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11817  *boundtype = SCIP_BOUNDTYPE_UPPER;
11818  else
11819  *boundtype = SCIP_BOUNDTYPE_LOWER;
11820  }
11821  *var = (*var)->data.multaggr.vars[0];
11822  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11823  }
11824  break;
11825 
11826  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11827  assert((*var)->data.aggregate.var != NULL);
11828  assert((*var)->data.aggregate.scalar != 0.0);
11829 
11830  (*bound) /= (*var)->data.aggregate.scalar;
11831  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11832  if( (*var)->data.aggregate.scalar < 0.0 )
11833  {
11834  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11835  *boundtype = SCIP_BOUNDTYPE_UPPER;
11836  else
11837  *boundtype = SCIP_BOUNDTYPE_LOWER;
11838  }
11839  *var = (*var)->data.aggregate.var;
11840  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11841  break;
11842 
11843  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11844  assert((*var)->negatedvar != NULL);
11845  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11846  assert((*var)->negatedvar->negatedvar == *var);
11847  (*bound) = (*var)->data.negate.constant - *bound;
11848  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11849  *boundtype = SCIP_BOUNDTYPE_UPPER;
11850  else
11851  *boundtype = SCIP_BOUNDTYPE_LOWER;
11852  *var = (*var)->negatedvar;
11853  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11854  break;
11855 
11856  default:
11857  SCIPerrorMessage("unknown variable status\n");
11858  return SCIP_INVALIDDATA;
11859  }
11860 
11861  return SCIP_OKAY;
11862 }
11863 
11864 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
11865  * values
11866  */
11868  SCIP_VAR** var, /**< pointer to problem variable */
11869  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
11870  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
11871  )
11872 {
11873  assert(var != NULL);
11874  assert(*var != NULL);
11875  assert(left != NULL);
11876  assert(right != NULL);
11877 
11878  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
11879 
11880  switch( SCIPvarGetStatus(*var) )
11881  {
11883  if( (*var)->data.original.transvar == NULL )
11884  {
11885  SCIPerrorMessage("original variable has no transformed variable attached\n");
11886  return SCIP_INVALIDDATA;
11887  }
11888  *var = (*var)->data.original.transvar;
11889  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11890  break;
11891 
11892  case SCIP_VARSTATUS_LOOSE:
11893  case SCIP_VARSTATUS_COLUMN:
11894  case SCIP_VARSTATUS_FIXED:
11896  break;
11897 
11898  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11899  assert((*var)->data.aggregate.var != NULL);
11900  assert((*var)->data.aggregate.scalar != 0.0);
11901 
11902  /* scale back */
11903  (*left) /= (*var)->data.aggregate.scalar;
11904  (*right) /= (*var)->data.aggregate.scalar;
11905 
11906  /* shift back */
11907  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11908  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11909 
11910  *var = (*var)->data.aggregate.var;
11911 
11912  /* check if the interval bounds have to swapped */
11913  if( (*var)->data.aggregate.scalar < 0.0 )
11914  {
11915  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11916  }
11917  else
11918  {
11919  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11920  }
11921  break;
11922 
11923  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11924  assert((*var)->negatedvar != NULL);
11925  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11926  assert((*var)->negatedvar->negatedvar == *var);
11927 
11928  /* shift and scale back */
11929  (*left) = (*var)->data.negate.constant - (*left);
11930  (*right) = (*var)->data.negate.constant - (*right);
11931 
11932  *var = (*var)->negatedvar;
11933 
11934  /* through the negated variable the left and right interval bound have to swapped */
11935  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
11936  break;
11937 
11938  default:
11939  SCIPerrorMessage("unknown variable status\n");
11940  return SCIP_INVALIDDATA;
11941  }
11942 
11943  return SCIP_OKAY;
11944 }
11945 
11946 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
11947  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
11948  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
11949  * with only one active variable (this can happen due to fixings after the multi-aggregation),
11950  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
11951  */
11953  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
11954  SCIP_SET* set, /**< global SCIP settings */
11955  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
11956  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
11957  )
11958 {
11959  assert(var != NULL);
11960  assert(scalar != NULL);
11961  assert(constant != NULL);
11962 
11963  while( *var != NULL )
11964  {
11965  switch( SCIPvarGetStatus(*var) )
11966  {
11968  if( (*var)->data.original.transvar == NULL )
11969  {
11970  SCIPerrorMessage("original variable has no transformed variable attached\n");
11971  return SCIP_INVALIDDATA;
11972  }
11973  *var = (*var)->data.original.transvar;
11974  break;
11975 
11976  case SCIP_VARSTATUS_LOOSE:
11977  case SCIP_VARSTATUS_COLUMN:
11978  return SCIP_OKAY;
11979 
11980  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
11981  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
11982  {
11983  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
11984  {
11985  assert(*scalar != 0.0);
11986  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
11987  (*constant) = SCIPsetInfinity(set);
11988  else
11989  (*constant) = -SCIPsetInfinity(set);
11990  }
11991  else
11992  (*constant) += *scalar * (*var)->glbdom.lb;
11993  }
11994 #ifndef NDEBUG
11995  else
11996  {
11997  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
11998  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
11999  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12000  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12001  }
12002 #endif
12003  *scalar = 0.0;
12004  return SCIP_OKAY;
12005 
12007  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12008  if ( (*var)->data.multaggr.nvars == 1 )
12009  {
12010  assert((*var)->data.multaggr.vars != NULL);
12011  assert((*var)->data.multaggr.scalars != NULL);
12012  assert((*var)->data.multaggr.vars[0] != NULL);
12013  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12014  {
12015  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12016  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12017  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12018  */
12019  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12020  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12021  {
12022  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12023  {
12024  assert(!SCIPsetIsInfinity(set, -(*constant)));
12025  (*constant) = SCIPsetInfinity(set);
12026  }
12027  else
12028  {
12029  assert(!SCIPsetIsInfinity(set, *constant));
12030  (*constant) = -SCIPsetInfinity(set);
12031  }
12032  (*scalar) = 0.0;
12033  }
12034  else
12035  (*constant) += *scalar * (*var)->data.multaggr.constant;
12036  }
12037  (*scalar) *= (*var)->data.multaggr.scalars[0];
12038  *var = (*var)->data.multaggr.vars[0];
12039  break;
12040  }
12041  return SCIP_OKAY;
12042 
12043  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12044  assert((*var)->data.aggregate.var != NULL);
12045  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12046  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12047  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12048  (*constant) += *scalar * (*var)->data.aggregate.constant;
12049  (*scalar) *= (*var)->data.aggregate.scalar;
12050  *var = (*var)->data.aggregate.var;
12051  break;
12052 
12053  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12054  assert((*var)->negatedvar != NULL);
12055  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12056  assert((*var)->negatedvar->negatedvar == *var);
12057  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12058  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12059  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12060  (*constant) += *scalar * (*var)->data.negate.constant;
12061  (*scalar) *= -1.0;
12062  *var = (*var)->negatedvar;
12063  break;
12064 
12065  default:
12066  SCIPerrorMessage("unknown variable status\n");
12067  SCIPABORT();
12068  return SCIP_INVALIDDATA; /*lint !e527*/
12069  }
12070  }
12071  *scalar = 0.0;
12072 
12073  return SCIP_OKAY;
12074 }
12075 
12076 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12077  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12078  */
12080  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12081  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12082  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12083  )
12084 {
12085  SCIP_VAR* parentvar;
12086 
12087  assert(var != NULL);
12088  assert(*var != NULL);
12089  assert(scalar != NULL);
12090  assert(constant != NULL);
12091 
12092  while( !SCIPvarIsOriginal(*var) )
12093  {
12094  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12095  * var
12096  */
12097  if( (*var)->nparentvars == 0 )
12098  {
12099  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12100  * space
12101  */
12103  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12104  {
12105  *scalar *= -1.0;
12106  *constant -= (*var)->data.negate.constant * (*scalar);
12107  *var = (*var)->negatedvar;
12108 
12109  continue;
12110  }
12111  /* if the variables does not have any parent the variables was created during solving and has no original
12112  * counterpart
12113  */
12114  else
12115  {
12116  *var = NULL;
12117 
12118  return SCIP_OKAY;
12119  }
12120  }
12121 
12122  /* follow the link to the first parent variable */
12123  parentvar = (*var)->parentvars[0];
12124  assert(parentvar != NULL);
12125 
12126  switch( SCIPvarGetStatus(parentvar) )
12127  {
12129  break;
12130 
12131  case SCIP_VARSTATUS_COLUMN:
12132  case SCIP_VARSTATUS_LOOSE:
12133  case SCIP_VARSTATUS_FIXED:
12135  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12136  return SCIP_INVALIDDATA;
12137 
12138  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12139  assert(parentvar->data.aggregate.var == *var);
12140  assert(parentvar->data.aggregate.scalar != 0.0);
12141  *scalar /= parentvar->data.aggregate.scalar;
12142  *constant -= parentvar->data.aggregate.constant * (*scalar);
12143  break;
12144 
12145  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12146  assert(parentvar->negatedvar != NULL);
12147  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12148  assert(parentvar->negatedvar->negatedvar == parentvar);
12149  *scalar *= -1.0;
12150  *constant -= parentvar->data.negate.constant * (*scalar);
12151  break;
12152 
12153  default:
12154  SCIPerrorMessage("unknown variable status\n");
12155  return SCIP_INVALIDDATA;
12156  }
12157 
12158  assert( parentvar != NULL );
12159  *var = parentvar;
12160  }
12161 
12162  return SCIP_OKAY;
12163 }
12164 
12165 /** returns whether the given variable is the direct counterpart of an original problem variable */
12167  SCIP_VAR* var /**< problem variable */
12168  )
12169 {
12170  SCIP_VAR* parentvar;
12171  assert(var != NULL);
12172 
12173  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12174  return FALSE;
12175 
12176  assert(var->parentvars != NULL);
12177  parentvar = var->parentvars[0];
12178  assert(parentvar != NULL);
12179 
12180  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12181  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12182  parentvar = parentvar->parentvars[0];
12183  assert( parentvar != NULL );
12184 
12185  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12186 }
12187 
12188 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12189  * the variable's own data due to diving, that operate only on the LP without updating the variables
12190  */
12192  SCIP_VAR* var /**< problem variable */
12193  )
12194 {
12195  assert(var != NULL);
12196 
12197  /* get bounds of attached variables */
12198  switch( SCIPvarGetStatus(var) )
12199  {
12201  assert(var->data.original.transvar != NULL);
12202  return SCIPvarGetObjLP(var->data.original.transvar);
12203 
12204  case SCIP_VARSTATUS_COLUMN:
12205  assert(var->data.col != NULL);
12206  return SCIPcolGetObj(var->data.col);
12207 
12208  case SCIP_VARSTATUS_LOOSE:
12209  case SCIP_VARSTATUS_FIXED:
12210  return var->obj;
12211 
12212  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12213  assert(var->data.aggregate.var != NULL);
12214  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12215 
12217  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12218  SCIPABORT();
12219  return 0.0; /*lint !e527*/
12220 
12221  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12222  assert(var->negatedvar != NULL);
12224  assert(var->negatedvar->negatedvar == var);
12225  return -SCIPvarGetObjLP(var->negatedvar);
12226 
12227  default:
12228  SCIPerrorMessage("unknown variable status\n");
12229  SCIPABORT();
12230  return 0.0; /*lint !e527*/
12231  }
12232 }
12233 
12234 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12235  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12236  */
12238  SCIP_VAR* var, /**< problem variable */
12239  SCIP_SET* set /**< global SCIP settings */
12240  )
12241 {
12242  assert(var != NULL);
12243  assert(set != NULL);
12244  assert(var->scip == set->scip);
12245 
12246  /* get bounds of attached variables */
12247  switch( SCIPvarGetStatus(var) )
12248  {
12250  assert(var->data.original.transvar != NULL);
12251  return SCIPvarGetLbLP(var->data.original.transvar, set);
12252 
12253  case SCIP_VARSTATUS_COLUMN:
12254  assert(var->data.col != NULL);
12255  return SCIPcolGetLb(var->data.col);
12256 
12257  case SCIP_VARSTATUS_LOOSE:
12258  case SCIP_VARSTATUS_FIXED:
12259  return var->locdom.lb;
12260 
12261  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12262  assert(var->data.aggregate.var != NULL);
12263  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12264  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12265  {
12266  return -SCIPsetInfinity(set);
12267  }
12268  else if( var->data.aggregate.scalar > 0.0 )
12269  {
12270  /* a > 0 -> get lower bound of y */
12271  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12272  }
12273  else if( var->data.aggregate.scalar < 0.0 )
12274  {
12275  /* a < 0 -> get upper bound of y */
12276  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12277  }
12278  else
12279  {
12280  SCIPerrorMessage("scalar is zero in aggregation\n");
12281  SCIPABORT();
12282  return SCIP_INVALID; /*lint !e527*/
12283  }
12284 
12286  /**@todo get the sides of the corresponding linear constraint */
12287  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12288  SCIPABORT();
12289  return SCIP_INVALID; /*lint !e527*/
12290 
12291  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12292  assert(var->negatedvar != NULL);
12294  assert(var->negatedvar->negatedvar == var);
12295  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12296 
12297  default:
12298  SCIPerrorMessage("unknown variable status\n");
12299  SCIPABORT();
12300  return SCIP_INVALID; /*lint !e527*/
12301  }
12302 }
12303 
12304 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12305  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12306  */
12308  SCIP_VAR* var, /**< problem variable */
12309  SCIP_SET* set /**< global SCIP settings */
12310  )
12311 {
12312  assert(var != NULL);
12313  assert(set != NULL);
12314  assert(var->scip == set->scip);
12315 
12316  /* get bounds of attached variables */
12317  switch( SCIPvarGetStatus(var) )
12318  {
12320  assert(var->data.original.transvar != NULL);
12321  return SCIPvarGetUbLP(var->data.original.transvar, set);
12322 
12323  case SCIP_VARSTATUS_COLUMN:
12324  assert(var->data.col != NULL);
12325  return SCIPcolGetUb(var->data.col);
12326 
12327  case SCIP_VARSTATUS_LOOSE:
12328  case SCIP_VARSTATUS_FIXED:
12329  return var->locdom.ub;
12330 
12331  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12332  assert(var->data.aggregate.var != NULL);
12333  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12334  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12335  {
12336  return SCIPsetInfinity(set);
12337  }
12338  if( var->data.aggregate.scalar > 0.0 )
12339  {
12340  /* a > 0 -> get upper bound of y */
12341  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12342  }
12343  else if( var->data.aggregate.scalar < 0.0 )
12344  {
12345  /* a < 0 -> get lower bound of y */
12346  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12347  }
12348  else
12349  {
12350  SCIPerrorMessage("scalar is zero in aggregation\n");
12351  SCIPABORT();
12352  return SCIP_INVALID; /*lint !e527*/
12353  }
12354 
12356  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12357  SCIPABORT();
12358  return SCIP_INVALID; /*lint !e527*/
12359 
12360  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12361  assert(var->negatedvar != NULL);
12363  assert(var->negatedvar->negatedvar == var);
12364  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12365 
12366  default:
12367  SCIPerrorMessage("unknown variable status\n");
12368  SCIPABORT();
12369  return SCIP_INVALID; /*lint !e527*/
12370  }
12371 }
12372 
12373 /** gets primal LP solution value of variable */
12375  SCIP_VAR* var /**< problem variable */
12376  )
12377 {
12378  assert(var != NULL);
12379 
12380  switch( SCIPvarGetStatus(var) )
12381  {
12383  if( var->data.original.transvar == NULL )
12384  return SCIP_INVALID;
12385  return SCIPvarGetLPSol(var->data.original.transvar);
12386 
12387  case SCIP_VARSTATUS_LOOSE:
12388  return SCIPvarGetBestBoundLocal(var);
12389 
12390  case SCIP_VARSTATUS_COLUMN:
12391  assert(var->data.col != NULL);
12392  return SCIPcolGetPrimsol(var->data.col);
12393 
12394  case SCIP_VARSTATUS_FIXED:
12395  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12396  return var->locdom.lb;
12397 
12399  {
12400  SCIP_Real lpsolval;
12401 
12402  assert(var->data.aggregate.var != NULL);
12403  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12404 
12405  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12406  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12407  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12408  * (or is called by) a public interface method; instead, we only assert that values are finite
12409  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12410  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12411  */
12412  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12413  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12414  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12415  }
12417  {
12418  SCIP_Real primsol;
12419  int i;
12420 
12421  assert(!var->donotmultaggr);
12422  assert(var->data.multaggr.vars != NULL);
12423  assert(var->data.multaggr.scalars != NULL);
12424  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12425  * assert(var->data.multaggr.nvars >= 2);
12426  */
12427  primsol = var->data.multaggr.constant;
12428  for( i = 0; i < var->data.multaggr.nvars; ++i )
12429  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12430  return primsol;
12431  }
12432  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12433  assert(var->negatedvar != NULL);
12435  assert(var->negatedvar->negatedvar == var);
12436  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12437 
12438  default:
12439  SCIPerrorMessage("unknown variable status\n");
12440  SCIPABORT();
12441  return SCIP_INVALID; /*lint !e527*/
12442  }
12443 }
12444 
12445 /** gets primal NLP solution value of variable */
12447  SCIP_VAR* var /**< problem variable */
12448  )
12449 {
12450  SCIP_Real solval;
12451  int i;
12452 
12453  assert(var != NULL);
12454 
12455  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12456  switch( SCIPvarGetStatus(var) )
12457  {
12459  return SCIPvarGetNLPSol(var->data.original.transvar);
12460 
12461  case SCIP_VARSTATUS_LOOSE:
12462  case SCIP_VARSTATUS_COLUMN:
12463  return var->nlpsol;
12464 
12465  case SCIP_VARSTATUS_FIXED:
12466  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12467  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12468  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12469  return SCIPvarGetLbGlobal(var);
12470 
12471  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12472  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12473  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12474 
12476  solval = var->data.multaggr.constant;
12477  for( i = 0; i < var->data.multaggr.nvars; ++i )
12478  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12479  return solval;
12480 
12482  solval = SCIPvarGetNLPSol(var->negatedvar);
12483  return var->data.negate.constant - solval;
12484 
12485  default:
12486  SCIPerrorMessage("unknown variable status\n");
12487  SCIPABORT();
12488  return SCIP_INVALID; /*lint !e527*/
12489  }
12490 }
12491 
12492 /** gets pseudo solution value of variable at current node */
12493 static
12495  SCIP_VAR* var /**< problem variable */
12496  )
12497 {
12498  SCIP_Real pseudosol;
12499  int i;
12500 
12501  assert(var != NULL);
12502 
12503  switch( SCIPvarGetStatus(var) )
12504  {
12506  if( var->data.original.transvar == NULL )
12507  return SCIP_INVALID;
12509 
12510  case SCIP_VARSTATUS_LOOSE:
12511  case SCIP_VARSTATUS_COLUMN:
12512  return SCIPvarGetBestBoundLocal(var);
12513 
12514  case SCIP_VARSTATUS_FIXED:
12515  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12516  return var->locdom.lb;
12517 
12519  {
12520  SCIP_Real pseudosolval;
12521  assert(var->data.aggregate.var != NULL);
12522  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12523  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12524  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12525  * (or is called by) a public interface method; instead, we only assert that values are finite
12526  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12527  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12528  */
12529  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12530  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12531  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12532  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12533  }
12535  assert(!var->donotmultaggr);
12536  assert(var->data.multaggr.vars != NULL);
12537  assert(var->data.multaggr.scalars != NULL);
12538  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12539  * assert(var->data.multaggr.nvars >= 2);
12540  */
12541  pseudosol = var->data.multaggr.constant;
12542  for( i = 0; i < var->data.multaggr.nvars; ++i )
12543  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12544  return pseudosol;
12545 
12546  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12547  assert(var->negatedvar != NULL);
12549  assert(var->negatedvar->negatedvar == var);
12550  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12551 
12552  default:
12553  SCIPerrorMessage("unknown variable status\n");
12554  SCIPABORT();
12555  return SCIP_INVALID; /*lint !e527*/
12556  }
12557 }
12558 
12559 /** gets current LP or pseudo solution value of variable */
12561  SCIP_VAR* var, /**< problem variable */
12562  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12563  )
12564 {
12565  if( getlpval )
12566  return SCIPvarGetLPSol(var);
12567  else
12568  return SCIPvarGetPseudoSol(var);
12569 }
12570 
12571 /** remembers the current solution as root solution in the problem variables */
12572 void SCIPvarStoreRootSol(
12573  SCIP_VAR* var, /**< problem variable */
12574  SCIP_Bool roothaslp /**< is the root solution from LP? */
12575  )
12576 {
12577  assert(var != NULL);
12578 
12579  var->rootsol = SCIPvarGetSol(var, roothaslp);
12580 }
12581 
12582 /** updates the current solution as best root solution of the given variable if it is better */
12584  SCIP_VAR* var, /**< problem variable */
12585  SCIP_SET* set, /**< global SCIP settings */
12586  SCIP_Real rootsol, /**< root solution value */
12587  SCIP_Real rootredcost, /**< root reduced cost */
12588  SCIP_Real rootlpobjval /**< objective value of the root LP */
12589  )
12590 {
12591  assert(var != NULL);
12592  assert(set != NULL);
12593  assert(var->scip == set->scip);
12594 
12595  /* if reduced cost are zero nothing to update */
12596  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12597  return;
12598 
12599  /* check if we have already a best combination stored */
12600  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12601  {
12602  SCIP_Real currcutoffbound;
12603  SCIP_Real cutoffbound;
12604  SCIP_Real bound;
12605 
12606  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12607  * root reduced cost, and root LP objective value combination
12608  */
12609  if( var->bestrootredcost > 0.0 )
12610  bound = SCIPvarGetUbGlobal(var);
12611  else
12612  bound = SCIPvarGetLbGlobal(var);
12613 
12614  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12615 
12616  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12617  * cost, and root LP objective value combination
12618  */
12619  if( rootredcost > 0.0 )
12620  bound = SCIPvarGetUbGlobal(var);
12621  else
12622  bound = SCIPvarGetLbGlobal(var);
12623 
12624  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12625 
12626  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12627  if( cutoffbound > currcutoffbound )
12628  {
12629  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12630  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12631 
12632  var->bestrootsol = rootsol;
12633  var->bestrootredcost = rootredcost;
12634  var->bestrootlpobjval = rootlpobjval;
12635  }
12636  }
12637  else
12638  {
12639  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12640  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12641  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12642  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12643 
12644  var->bestrootsol = rootsol;
12645  var->bestrootredcost = rootredcost;
12646  var->bestrootlpobjval = rootlpobjval;
12647  }
12648 }
12649 
12650 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12651  * completely solved, zero is returned
12652  */
12654  SCIP_VAR* var /**< problem variable */
12655  )
12656 {
12657  SCIP_Real rootsol;
12658  int i;
12659 
12660  assert(var != NULL);
12661 
12662  switch( SCIPvarGetStatus(var) )
12663  {
12665  if( var->data.original.transvar == NULL )
12666  return 0.0;
12667  return SCIPvarGetRootSol(var->data.original.transvar);
12668 
12669  case SCIP_VARSTATUS_LOOSE:
12670  case SCIP_VARSTATUS_COLUMN:
12671  return var->rootsol;
12672 
12673  case SCIP_VARSTATUS_FIXED:
12674  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12675  return var->locdom.lb;
12676 
12678  assert(var->data.aggregate.var != NULL);
12679  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12680  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12681  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12682  * (or is called by) a public interface method; instead, we only assert that values are finite
12683  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12684  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12685  */
12689 
12691  assert(!var->donotmultaggr);
12692  assert(var->data.multaggr.vars != NULL);
12693  assert(var->data.multaggr.scalars != NULL);
12694  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12695  * assert(var->data.multaggr.nvars >= 2);
12696  */
12697  rootsol = var->data.multaggr.constant;
12698  for( i = 0; i < var->data.multaggr.nvars; ++i )
12699  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12700  return rootsol;
12701 
12702  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12703  assert(var->negatedvar != NULL);
12705  assert(var->negatedvar->negatedvar == var);
12706  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12707 
12708  default:
12709  SCIPerrorMessage("unknown variable status\n");
12710  SCIPABORT();
12711  return SCIP_INVALID; /*lint !e527*/
12712  }
12713 }
12714 
12715 /** returns for given variable the reduced cost */
12716 static
12718  SCIP_VAR* var, /**< problem variable */
12719  SCIP_SET* set, /**< global SCIP settings */
12720  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12721  SCIP_STAT* stat, /**< problem statistics */
12722  SCIP_LP* lp /**< current LP data */
12723  )
12724 {
12726  {
12727  SCIP_COL* col;
12728  SCIP_Real primsol;
12729  SCIP_BASESTAT basestat;
12730  SCIP_Bool lpissolbasic;
12731 
12732  col = SCIPvarGetCol(var);
12733  assert(col != NULL);
12734 
12735  basestat = SCIPcolGetBasisStatus(col);
12736  lpissolbasic = SCIPlpIsSolBasic(lp);
12737  primsol = SCIPcolGetPrimsol(col);
12738 
12739  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12740  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12741  {
12742  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12743 
12744  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12745  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12747  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12748  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12749  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12750 
12751  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12752  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12753  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12754  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12755  return redcost;
12756  else
12757  return 0.0;
12758  }
12759 
12760  return 0.0;
12761  }
12762 
12763  return 0.0;
12764 }
12765 
12766 #define MAX_CLIQUELENGTH 50
12767 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12768  * the binary variable is fixed to the given value
12769  */
12771  SCIP_VAR* var, /**< problem variable */
12772  SCIP_SET* set, /**< global SCIP settings */
12773  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12774  SCIP_STAT* stat, /**< problem statistics */
12775  SCIP_PROB* prob, /**< transformed problem, or NULL */
12776  SCIP_LP* lp /**< current LP data */
12777  )
12778 {
12779  SCIP_Real implredcost;
12780  int ncliques;
12781  int nvars;
12782 
12783  assert(SCIPvarIsBinary(var));
12784  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12785 
12786  /* get reduced cost of given variable */
12787  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12788 
12789 #ifdef SCIP_MORE_DEBUG
12790  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12791 #endif
12792 
12793  /* the following algorithm is expensive */
12794  ncliques = SCIPvarGetNCliques(var, varfixing);
12795 
12796  if( ncliques > 0 )
12797  {
12798  SCIP_CLIQUE** cliques;
12799  SCIP_CLIQUE* clique;
12800  SCIP_VAR** clqvars;
12801  SCIP_VAR** probvars;
12802  SCIP_VAR* clqvar;
12803  SCIP_Bool* clqvalues;
12804  int* entries;
12805  int* ids;
12806  SCIP_Real redcost;
12807  SCIP_Bool cleanedup;
12808  int nclqvars;
12809  int nentries;
12810  int nids;
12811  int id;
12812  int c;
12813  int v;
12814 
12815  assert(prob != NULL);
12816  assert(SCIPprobIsTransformed(prob));
12817 
12818  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12819 
12820  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
12821  nids = 0;
12822  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
12823 
12824  cliques = SCIPvarGetCliques(var, varfixing);
12825  assert(cliques != NULL);
12826 
12827  for( c = ncliques - 1; c >= 0; --c )
12828  {
12829  clique = cliques[c];
12830  assert(clique != NULL);
12831  nclqvars = SCIPcliqueGetNVars(clique);
12832  assert(nclqvars > 0);
12833 
12834  if( nclqvars > MAX_CLIQUELENGTH )
12835  continue;
12836 
12837  clqvars = SCIPcliqueGetVars(clique);
12838  clqvalues = SCIPcliqueGetValues(clique);
12839  assert(clqvars != NULL);
12840  assert(clqvalues != NULL);
12841 
12842  cleanedup = SCIPcliqueIsCleanedUp(clique);
12843 
12844  for( v = nclqvars - 1; v >= 0; --v )
12845  {
12846  clqvar = clqvars[v];
12847  assert(clqvar != NULL);
12848 
12849  /* ignore binary variable which are fixed */
12850  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
12851  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
12852  {
12853  int probindex = SCIPvarGetProbindex(clqvar) + 1;
12854  assert(0 < probindex && probindex < nentries);
12855 
12856 #if 0
12857  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
12858  * can appear since there is no guarantee that all these infeasible bounds were found
12859  */
12860  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
12861 #endif
12862  if( entries[probindex] == 0 )
12863  {
12864  ids[nids] = probindex;
12865  ++nids;
12866 
12867  /* mark variable as visited */
12868  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
12869  }
12870  }
12871  }
12872  }
12873 
12874  probvars = SCIPprobGetVars(prob);
12875  assert(probvars != NULL);
12876 
12877  /* add all implied reduced cost */
12878  for( v = nids - 1; v >= 0; --v )
12879  {
12880  id = ids[v];
12881  assert(0 < id && id < nentries);
12882  assert(entries[id] != 0);
12883  assert(probvars[id - 1] != NULL);
12884  assert(SCIPvarIsActive(probvars[id - 1]));
12885  assert(SCIPvarIsBinary(probvars[id - 1]));
12886  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
12887 
12888  if( (entries[id] > 0) != varfixing )
12889  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12890  else
12891  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12892 
12893  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
12894  implredcost += redcost;
12895 
12896  /* reset entries clear buffer array */
12897  entries[id] = 0;
12898  }
12899 
12900  SCIPsetFreeCleanBufferArray(set, &entries);
12901  SCIPsetFreeBufferArray(set, &ids);
12902  }
12903 
12904 #ifdef SCIP_MORE_DEBUG
12905  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
12906  implredcost);
12907 #endif
12908 
12909  /* collect non-binary implication information */
12910  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
12911 
12912  if( nvars > 0 )
12913  {
12914  SCIP_VAR** vars;
12915  SCIP_VAR* implvar;
12916  SCIP_COL* col;
12917  SCIP_Real* bounds;
12918  SCIP_BOUNDTYPE* boundtypes;
12919  SCIP_Real redcost;
12920  SCIP_Real lb;
12921  SCIP_Real ub;
12922  SCIP_Bool lpissolbasic;
12923  int v;
12924 
12925  vars = SCIPimplicsGetVars(var->implics, varfixing);
12926  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
12927  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
12928  lpissolbasic = SCIPlpIsSolBasic(lp);
12929 
12930  for( v = nvars - 1; v >= 0; --v )
12931  {
12932  implvar = vars[v];
12933  assert(implvar != NULL);
12934 
12935  lb = SCIPvarGetLbLocal(implvar);
12936  ub = SCIPvarGetUbLocal(implvar);
12937 
12938  /* ignore binary variable which are fixed or not of column status */
12939  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
12940  continue;
12941 
12942  col = SCIPvarGetCol(implvar);
12943  assert(col != NULL);
12944  redcost = 0.0;
12945 
12946  /* solved lp with basis information or not? */
12947  if( lpissolbasic )
12948  {
12949  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
12950 
12951  /* check if the implication is not not yet applied */
12952  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
12953  {
12954  redcost = SCIPcolGetRedcost(col, stat, lp);
12955  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12956 
12957  if( !varfixing )
12958  redcost *= (lb - bounds[v]);
12959  else
12960  redcost *= (bounds[v] - lb);
12961  }
12962  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
12963  {
12964  redcost = SCIPcolGetRedcost(col, stat, lp);
12965  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12966 
12967  if( varfixing )
12968  redcost *= (bounds[v] - ub);
12969  else
12970  redcost *= (ub - bounds[v]);
12971  }
12972  }
12973  else
12974  {
12975  SCIP_Real primsol = SCIPcolGetPrimsol(col);
12976 
12977  /* check if the implication is not not yet applied */
12978  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
12979  {
12980  redcost = SCIPcolGetRedcost(col, stat, lp);
12981  assert(!SCIPsetIsDualfeasNegative(set, redcost));
12982 
12983  if( varfixing )
12984  redcost *= (lb - bounds[v]);
12985  else
12986  redcost *= (bounds[v] - lb);
12987  }
12988  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
12989  {
12990  redcost = SCIPcolGetRedcost(col, stat, lp);
12991  assert(!SCIPsetIsDualfeasPositive(set, redcost));
12992 
12993  if( varfixing )
12994  redcost *= (bounds[v] - ub);
12995  else
12996  redcost *= (ub - bounds[v]);
12997  }
12998  }
12999 
13000  /* improve implied reduced cost */
13001  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13002  implredcost += redcost;
13003  }
13004  }
13005 
13006 #ifdef SCIP_MORE_DEBUG
13007  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13008  SCIPvarGetName(var), ncliques, nvars, implredcost);
13009 #endif
13010 
13011  return implredcost;
13012 }
13013 
13014 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13015  * the root relaxation is not yet completely solved, zero is returned
13016  */
13018  SCIP_VAR* var /**< problem variable */
13019  )
13020 {
13021  SCIP_Real rootsol;
13022  int i;
13023 
13024  assert(var != NULL);
13025 
13026  switch( SCIPvarGetStatus(var) )
13027  {
13029  if( var->data.original.transvar == NULL )
13030  return 0.0;
13032 
13033  case SCIP_VARSTATUS_LOOSE:
13034  case SCIP_VARSTATUS_COLUMN:
13035  return var->bestrootsol;
13036 
13037  case SCIP_VARSTATUS_FIXED:
13038  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13039  return var->locdom.lb;
13040 
13042  assert(var->data.aggregate.var != NULL);
13043  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13044  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13045  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13046  * (or is called by) a public interface method; instead, we only assert that values are finite
13047  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13048  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13049  */
13053 
13055  assert(!var->donotmultaggr);
13056  assert(var->data.multaggr.vars != NULL);
13057  assert(var->data.multaggr.scalars != NULL);
13058  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13059  * assert(var->data.multaggr.nvars >= 2);
13060  */
13061  rootsol = var->data.multaggr.constant;
13062  for( i = 0; i < var->data.multaggr.nvars; ++i )
13063  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13064  return rootsol;
13065 
13066  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13067  assert(var->negatedvar != NULL);
13069  assert(var->negatedvar->negatedvar == var);
13070  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13071 
13072  default:
13073  SCIPerrorMessage("unknown variable status\n");
13074  SCIPABORT();
13075  return 0.0; /*lint !e527*/
13076  }
13077 }
13078 
13079 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13080  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13081  * returned
13082  */
13084  SCIP_VAR* var /**< problem variable */
13085  )
13086 {
13087  assert(var != NULL);
13088 
13089  switch( SCIPvarGetStatus(var) )
13090  {
13092  if( var->data.original.transvar == NULL )
13093  return SCIP_INVALID;
13095 
13096  case SCIP_VARSTATUS_LOOSE:
13097  case SCIP_VARSTATUS_COLUMN:
13098  return var->bestrootredcost;
13099 
13100  case SCIP_VARSTATUS_FIXED:
13104  return 0.0;
13105 
13106  default:
13107  SCIPerrorMessage("unknown variable status\n");
13108  SCIPABORT();
13109  return 0.0; /*lint !e527*/
13110  }
13111 }
13112 
13113 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13114  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13115  * SCIP_INVALID is returned
13116  */
13118  SCIP_VAR* var /**< problem variable */
13119  )
13120 {
13121  assert(var != NULL);
13122 
13123  switch( SCIPvarGetStatus(var) )
13124  {
13126  if( var->data.original.transvar == NULL )
13127  return SCIP_INVALID;
13129 
13130  case SCIP_VARSTATUS_LOOSE:
13131  case SCIP_VARSTATUS_COLUMN:
13132  return var->bestrootlpobjval;
13133 
13134  case SCIP_VARSTATUS_FIXED:
13138  return SCIP_INVALID;
13139 
13140  default:
13141  SCIPerrorMessage("unknown variable status\n");
13142  SCIPABORT();
13143  return SCIP_INVALID; /*lint !e527*/
13144  }
13145 }
13146 
13147 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13149  SCIP_VAR* var, /**< problem variable */
13150  SCIP_Real rootsol, /**< root solution value */
13151  SCIP_Real rootredcost, /**< root reduced cost */
13152  SCIP_Real rootlpobjval /**< objective value of the root LP */
13153  )
13154 {
13155  assert(var != NULL);
13156 
13157  var->bestrootsol = rootsol;
13158  var->bestrootredcost = rootredcost;
13159  var->bestrootlpobjval = rootlpobjval;
13160 }
13161 
13162 /** stores the solution value as relaxation solution in the problem variable */
13164  SCIP_VAR* var, /**< problem variable */
13165  SCIP_SET* set, /**< global SCIP settings */
13166  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13167  SCIP_Real solval, /**< solution value in the current relaxation solution */
13168  SCIP_Bool updateobj /**< should the objective value be updated? */
13169  )
13170 {
13171  assert(var != NULL);
13172  assert(relaxation != NULL);
13173  assert(set != NULL);
13174  assert(var->scip == set->scip);
13175 
13176  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13177  switch( SCIPvarGetStatus(var) )
13178  {
13180  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13181  break;
13182 
13183  case SCIP_VARSTATUS_LOOSE:
13184  case SCIP_VARSTATUS_COLUMN:
13185  if( updateobj )
13186  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13187  var->relaxsol = solval;
13188  break;
13189 
13190  case SCIP_VARSTATUS_FIXED:
13191  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13192  {
13193  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13194  SCIPvarGetName(var), var->glbdom.lb, solval);
13195  return SCIP_INVALIDDATA;
13196  }
13197  break;
13198 
13199  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13200  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13201  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13202  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13203  break;
13205  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13206  return SCIP_INVALIDDATA;
13207 
13209  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13210  break;
13211 
13212  default:
13213  SCIPerrorMessage("unknown variable status\n");
13214  return SCIP_INVALIDDATA;
13215  }
13216 
13217  return SCIP_OKAY;
13218 }
13219 
13220 /** returns the solution value of the problem variable in the relaxation solution
13221  *
13222  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13223  */
13225  SCIP_VAR* var, /**< problem variable */
13226  SCIP_SET* set /**< global SCIP settings */
13227  )
13228 {
13229  SCIP_Real solvalsum;
13230  SCIP_Real solval;
13231  int i;
13232 
13233  assert(var != NULL);
13234  assert(set != NULL);
13235  assert(var->scip == set->scip);
13236 
13237  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13238  switch( SCIPvarGetStatus(var) )
13239  {
13241  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13242 
13243  case SCIP_VARSTATUS_LOOSE:
13244  case SCIP_VARSTATUS_COLUMN:
13245  return var->relaxsol;
13246 
13247  case SCIP_VARSTATUS_FIXED:
13248  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13249  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13250  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13251  return SCIPvarGetLbGlobal(var);
13252 
13253  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13254  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13255  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13256  {
13257  if( var->data.aggregate.scalar * solval > 0.0 )
13258  return SCIPsetInfinity(set);
13259  if( var->data.aggregate.scalar * solval < 0.0 )
13260  return -SCIPsetInfinity(set);
13261  }
13262  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13263 
13265  solvalsum = var->data.multaggr.constant;
13266  for( i = 0; i < var->data.multaggr.nvars; ++i )
13267  {
13268  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13269  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13270  {
13271  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13272  return SCIPsetInfinity(set);
13273  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13274  return -SCIPsetInfinity(set);
13275  }
13276  solvalsum += var->data.multaggr.scalars[i] * solval;
13277  }
13278  return solvalsum;
13279 
13281  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13282  if( SCIPsetIsInfinity(set, solval) )
13283  return -SCIPsetInfinity(set);
13284  if( SCIPsetIsInfinity(set, -solval) )
13285  return SCIPsetInfinity(set);
13286  return var->data.negate.constant - solval;
13287 
13288  default:
13289  SCIPerrorMessage("unknown variable status\n");
13290  SCIPABORT();
13291  return SCIP_INVALID; /*lint !e527*/
13292  }
13293 }
13294 
13295 /** returns the solution value of the transformed problem variable in the relaxation solution */
13297  SCIP_VAR* var /**< problem variable */
13298  )
13299 {
13300  assert(var != NULL);
13302 
13303  return var->relaxsol;
13304 }
13305 
13306 /** stores the solution value as NLP solution in the problem variable */
13308  SCIP_VAR* var, /**< problem variable */
13309  SCIP_SET* set, /**< global SCIP settings */
13310  SCIP_Real solval /**< solution value in the current NLP solution */
13311  )
13312 {
13313  assert(var != NULL);
13314  assert(set != NULL);
13315  assert(var->scip == set->scip);
13316 
13317  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13318  switch( SCIPvarGetStatus(var) )
13319  {
13321  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13322  break;
13323 
13324  case SCIP_VARSTATUS_LOOSE:
13325  case SCIP_VARSTATUS_COLUMN:
13326  var->nlpsol = solval;
13327  break;
13328 
13329  case SCIP_VARSTATUS_FIXED:
13330  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13331  {
13332  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13333  SCIPvarGetName(var), var->glbdom.lb, solval);
13334  SCIPABORT();
13335  return SCIP_INVALIDCALL; /*lint !e527*/
13336  }
13337  break;
13338 
13339  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13340  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13341  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13342  break;
13343 
13345  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13346  SCIPABORT();
13347  return SCIP_INVALIDCALL; /*lint !e527*/
13348 
13350  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13351  break;
13352 
13353  default:
13354  SCIPerrorMessage("unknown variable status\n");
13355  SCIPABORT();
13356  return SCIP_ERROR; /*lint !e527*/
13357  }
13358 
13359  return SCIP_OKAY;
13360 }
13361 
13362 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13364  SCIP_VAR* var /**< problem variable */
13365  )
13366 {
13367  SCIP_Real avgsol;
13368  int i;
13369 
13370  assert(var != NULL);
13371 
13372  switch( SCIPvarGetStatus(var) )
13373  {
13375  if( var->data.original.transvar == NULL )
13376  return 0.0;
13377  return SCIPvarGetAvgSol(var->data.original.transvar);
13378 
13379  case SCIP_VARSTATUS_LOOSE:
13380  case SCIP_VARSTATUS_COLUMN:
13381  avgsol = var->primsolavg;
13382  avgsol = MAX(avgsol, var->glbdom.lb);
13383  avgsol = MIN(avgsol, var->glbdom.ub);
13384  return avgsol;
13385 
13386  case SCIP_VARSTATUS_FIXED:
13387  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13388  return var->locdom.lb;
13389 
13391  assert(var->data.aggregate.var != NULL);
13392  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13393  + var->data.aggregate.constant;
13394 
13396  assert(!var->donotmultaggr);
13397  assert(var->data.multaggr.vars != NULL);
13398  assert(var->data.multaggr.scalars != NULL);
13399  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13400  * assert(var->data.multaggr.nvars >= 2);
13401  */
13402  avgsol = var->data.multaggr.constant;
13403  for( i = 0; i < var->data.multaggr.nvars; ++i )
13404  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13405  return avgsol;
13406 
13407  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13408  assert(var->negatedvar != NULL);
13410  assert(var->negatedvar->negatedvar == var);
13411  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13412 
13413  default:
13414  SCIPerrorMessage("unknown variable status\n");
13415  SCIPABORT();
13416  return 0.0; /*lint !e527*/
13417  }
13418 }
13419 
13420 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13421  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13422  */
13424  SCIP_VAR* var, /**< active problem variable */
13425  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13426  SCIP_SET* set, /**< global SCIP settings */
13427  SCIP_STAT* stat, /**< problem statistics */
13428  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13429  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13430  )
13431 {
13432  int nvlbs;
13433 
13434  assert(var != NULL);
13435  assert(stat != NULL);
13436  assert(set != NULL);
13437  assert(var->scip == set->scip);
13438  assert(closestvlb != NULL);
13439  assert(closestvlbidx != NULL);
13440 
13441  *closestvlbidx = -1;
13442  *closestvlb = SCIP_REAL_MIN;
13443 
13444  nvlbs = SCIPvarGetNVlbs(var);
13445  if( nvlbs > 0 )
13446  {
13447  SCIP_VAR** vlbvars;
13448  SCIP_Real* vlbcoefs;
13449  SCIP_Real* vlbconsts;
13450  int i;
13451 
13452  vlbvars = SCIPvarGetVlbVars(var);
13453  vlbcoefs = SCIPvarGetVlbCoefs(var);
13454  vlbconsts = SCIPvarGetVlbConstants(var);
13455 
13456  /* check for cached values */
13457  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13458  {
13459  i = var->closestvlbidx;
13460  assert(0 <= i && i < nvlbs);
13461  assert(SCIPvarIsActive(vlbvars[i]));
13462  *closestvlbidx = i;
13463  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13464  }
13465  else
13466  {
13467  /* search best VUB */
13468  for( i = 0; i < nvlbs; i++ )
13469  {
13470  if( SCIPvarIsActive(vlbvars[i]) )
13471  {
13472  SCIP_Real vlbsol;
13473 
13474  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13475  if( vlbsol > *closestvlb )
13476  {
13477  *closestvlb = vlbsol;
13478  *closestvlbidx = i;
13479  }
13480  }
13481  }
13482 
13483  if( sol == NULL )
13484  {
13485  /* update cached value */
13486  if( var->closestvblpcount != stat->lpcount )
13487  var->closestvubidx = -1;
13488  var->closestvlbidx = *closestvlbidx;
13489  var->closestvblpcount = stat->lpcount;
13490  }
13491  }
13492  }
13493 }
13494 
13495 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13496  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13497  */
13499  SCIP_VAR* var, /**< active problem variable */
13500  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13501  SCIP_SET* set, /**< global SCIP settings */
13502  SCIP_STAT* stat, /**< problem statistics */
13503  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13504  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13505  )
13506 {
13507  int nvubs;
13508 
13509  assert(var != NULL);
13510  assert(set != NULL);
13511  assert(var->scip == set->scip);
13512  assert(closestvub != NULL);
13513  assert(closestvubidx != NULL);
13514 
13515  *closestvubidx = -1;
13516  *closestvub = SCIP_REAL_MAX;
13517 
13518  nvubs = SCIPvarGetNVubs(var);
13519  if( nvubs > 0 )
13520  {
13521  SCIP_VAR** vubvars;
13522  SCIP_Real* vubcoefs;
13523  SCIP_Real* vubconsts;
13524  int i;
13525 
13526  vubvars = SCIPvarGetVubVars(var);
13527  vubcoefs = SCIPvarGetVubCoefs(var);
13528  vubconsts = SCIPvarGetVubConstants(var);
13529 
13530  /* check for cached values */
13531  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13532  {
13533  i = var->closestvubidx;
13534  assert(0 <= i && i < nvubs);
13535  assert(SCIPvarIsActive(vubvars[i]));
13536  *closestvubidx = i;
13537  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13538  }
13539  else
13540  {
13541  /* search best VUB */
13542  for( i = 0; i < nvubs; i++ )
13543  {
13544  if( SCIPvarIsActive(vubvars[i]) )
13545  {
13546  SCIP_Real vubsol;
13547 
13548  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13549  if( vubsol < *closestvub )
13550  {
13551  *closestvub = vubsol;
13552  *closestvubidx = i;
13553  }
13554  }
13555  }
13556 
13557  if( sol == NULL )
13558  {
13559  /* update cached value */
13560  if( var->closestvblpcount != stat->lpcount )
13561  var->closestvlbidx = -1;
13562  var->closestvubidx = *closestvubidx;
13563  var->closestvblpcount = stat->lpcount;
13564  }
13565  }
13566  }
13567 }
13568 
13569 /** resolves variable to columns and adds them with the coefficient to the row */
13571  SCIP_VAR* var, /**< problem variable */
13572  BMS_BLKMEM* blkmem, /**< block memory */
13573  SCIP_SET* set, /**< global SCIP settings */
13574  SCIP_STAT* stat, /**< problem statistics */
13575  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13576  SCIP_PROB* prob, /**< problem data */
13577  SCIP_LP* lp, /**< current LP data */
13578  SCIP_ROW* row, /**< LP row */
13579  SCIP_Real val /**< value of coefficient */
13580  )
13581 {
13582  int i;
13583 
13584  assert(var != NULL);
13585  assert(set != NULL);
13586  assert(var->scip == set->scip);
13587  assert(row != NULL);
13588  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13589 
13590  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13591 
13592  if ( SCIPsetIsZero(set, val) )
13593  return SCIP_OKAY;
13594 
13595  switch( SCIPvarGetStatus(var) )
13596  {
13598  if( var->data.original.transvar == NULL )
13599  {
13600  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13601  return SCIP_INVALIDDATA;
13602  }
13603  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13604  return SCIP_OKAY;
13605 
13606  case SCIP_VARSTATUS_LOOSE:
13607  /* add globally fixed variables as constant */
13608  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13609  {
13610  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13611  return SCIP_OKAY;
13612  }
13613  /* convert loose variable into column */
13614  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13615  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13616  /*lint -fallthrough*/
13617 
13618  case SCIP_VARSTATUS_COLUMN:
13619  assert(var->data.col != NULL);
13620  assert(var->data.col->var == var);
13621  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13622  return SCIP_OKAY;
13623 
13624  case SCIP_VARSTATUS_FIXED:
13625  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13626  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13627  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13628  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13629  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13630  return SCIP_OKAY;
13631 
13633  assert(var->data.aggregate.var != NULL);
13634  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13635  row, var->data.aggregate.scalar * val) );
13636  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13637  return SCIP_OKAY;
13638 
13640  assert(!var->donotmultaggr);
13641  assert(var->data.multaggr.vars != NULL);
13642  assert(var->data.multaggr.scalars != NULL);
13643  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13644  * assert(var->data.multaggr.nvars >= 2);
13645  */
13646  for( i = 0; i < var->data.multaggr.nvars; ++i )
13647  {
13648  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13649  row, var->data.multaggr.scalars[i] * val) );
13650  }
13651  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13652  return SCIP_OKAY;
13653 
13654  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13655  assert(var->negatedvar != NULL);
13657  assert(var->negatedvar->negatedvar == var);
13658  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13659  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13660  return SCIP_OKAY;
13661 
13662  default:
13663  SCIPerrorMessage("unknown variable status\n");
13664  return SCIP_INVALIDDATA;
13665  }
13666 }
13667 
13668 /* optionally, define this compiler flag to write complete variable histories to a file */
13669 #ifdef SCIP_HISTORYTOFILE
13670 SCIP_Longint counter = 0l;
13671 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13672 #include "scip/scip.h"
13673 #endif
13674 
13675 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13676  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13677  */
13679  SCIP_VAR* var, /**< problem variable */
13680  SCIP_SET* set, /**< global SCIP settings */
13681  SCIP_STAT* stat, /**< problem statistics */
13682  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13683  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13684  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13685  )
13686 {
13687  SCIP_Real oldrootpseudocosts;
13688  assert(var != NULL);
13689  assert(set != NULL);
13690  assert(var->scip == set->scip);
13691  assert(stat != NULL);
13692 
13693  /* check if history statistics should be collected for a variable */
13694  if( !stat->collectvarhistory )
13695  return SCIP_OKAY;
13696 
13697  switch( SCIPvarGetStatus(var) )
13698  {
13700  if( var->data.original.transvar == NULL )
13701  {
13702  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13703  return SCIP_INVALIDDATA;
13704  }
13705  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13706  return SCIP_OKAY;
13707 
13708  case SCIP_VARSTATUS_LOOSE:
13709  case SCIP_VARSTATUS_COLUMN:
13710  /* store old pseudo-costs for root LP best-estimate update */
13711  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13712 
13713  /* update history */
13714  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13715  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13716  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13717  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13718 
13719  /* update root LP best-estimate */
13720  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13721 
13722  /* append history to file */
13723 #ifdef SCIP_HISTORYTOFILE
13724  {
13725  FILE* f;
13726  char filename[256];
13727  SCIP_NODE* currentnode;
13728  SCIP_NODE* parentnode;
13729  currentnode = SCIPgetFocusNode(set->scip);
13730  parentnode = SCIPnodeGetParent(currentnode);
13731 
13732  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13733  f = fopen(filename, "a");
13734  if( NULL != f )
13735  {
13736  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13737  ++counter,
13738  SCIPvarGetName(var),
13739  SCIPnodeGetNumber(currentnode),
13740  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13741  SCIPgetNLPIterations(set->scip),
13742  SCIPgetDepth(set->scip),
13743  objdelta,
13744  solvaldelta);
13745  fclose(f);
13746  }
13747  }
13748 #endif
13749  return SCIP_OKAY;
13750 
13751  case SCIP_VARSTATUS_FIXED:
13752  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13753  return SCIP_INVALIDDATA;
13754 
13756  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13758  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13759  return SCIP_OKAY;
13760 
13762  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13763  return SCIP_INVALIDDATA;
13764 
13766  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13767  return SCIP_OKAY;
13768 
13769  default:
13770  SCIPerrorMessage("unknown variable status\n");
13771  return SCIP_INVALIDDATA;
13772  }
13773 }
13774 
13775 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13777  SCIP_VAR* var, /**< problem variable */
13778  SCIP_STAT* stat, /**< problem statistics */
13779  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13780  )
13781 {
13782  SCIP_BRANCHDIR dir;
13783 
13784  assert(var != NULL);
13785  assert(stat != NULL);
13786 
13787  switch( SCIPvarGetStatus(var) )
13788  {
13790  if( var->data.original.transvar == NULL )
13791  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13792  else
13793  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13794 
13795  case SCIP_VARSTATUS_LOOSE:
13796  case SCIP_VARSTATUS_COLUMN:
13797  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13798 
13799  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13800  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13801  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13802 
13803  case SCIP_VARSTATUS_FIXED:
13804  return 0.0;
13805 
13807  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13808 
13810  return 0.0;
13811 
13813  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13814 
13815  default:
13816  SCIPerrorMessage("unknown variable status\n");
13817  SCIPABORT();
13818  return 0.0; /*lint !e527*/
13819  }
13820 }
13821 
13822 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13823  * only using the pseudo cost information of the current run
13824  */
13826  SCIP_VAR* var, /**< problem variable */
13827  SCIP_STAT* stat, /**< problem statistics */
13828  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13829  )
13830 {
13831  SCIP_BRANCHDIR dir;
13832 
13833  assert(var != NULL);
13834  assert(stat != NULL);
13835 
13836  switch( SCIPvarGetStatus(var) )
13837  {
13839  if( var->data.original.transvar == NULL )
13840  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13841  else
13842  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
13843 
13844  case SCIP_VARSTATUS_LOOSE:
13845  case SCIP_VARSTATUS_COLUMN:
13846  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13847 
13848  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
13849  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
13850  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13851 
13852  case SCIP_VARSTATUS_FIXED:
13853  return 0.0;
13854 
13856  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13857 
13859  return 0.0;
13860 
13862  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
13863 
13864  default:
13865  SCIPerrorMessage("unknown variable status\n");
13866  SCIPABORT();
13867  return 0.0; /*lint !e527*/
13868  }
13869 }
13870 
13871 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
13873  SCIP_VAR* var, /**< problem variable */
13874  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13875  )
13876 {
13877  assert(var != NULL);
13878  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13879 
13880  switch( SCIPvarGetStatus(var) )
13881  {
13883  if( var->data.original.transvar == NULL )
13884  return 0.0;
13885  else
13886  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
13887 
13888  case SCIP_VARSTATUS_LOOSE:
13889  case SCIP_VARSTATUS_COLUMN:
13890  return SCIPhistoryGetPseudocostCount(var->history, dir);
13891 
13892  case SCIP_VARSTATUS_FIXED:
13893  return 0.0;
13894 
13896  if( var->data.aggregate.scalar > 0.0 )
13897  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
13898  else
13900 
13902  return 0.0;
13903 
13906 
13907  default:
13908  SCIPerrorMessage("unknown variable status\n");
13909  SCIPABORT();
13910  return 0.0; /*lint !e527*/
13911  }
13912 }
13913 
13914 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
13915  * only using the pseudo cost information of the current run
13916  */
13918  SCIP_VAR* var, /**< problem variable */
13919  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13920  )
13921 {
13922  assert(var != NULL);
13923  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13924 
13925  switch( SCIPvarGetStatus(var) )
13926  {
13928  if( var->data.original.transvar == NULL )
13929  return 0.0;
13930  else
13932 
13933  case SCIP_VARSTATUS_LOOSE:
13934  case SCIP_VARSTATUS_COLUMN:
13935  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
13936 
13937  case SCIP_VARSTATUS_FIXED:
13938  return 0.0;
13939 
13941  if( var->data.aggregate.scalar > 0.0 )
13943  else
13945 
13947  return 0.0;
13948 
13951 
13952  default:
13953  SCIPerrorMessage("unknown variable status\n");
13954  SCIPABORT();
13955  return 0.0; /*lint !e527*/
13956  }
13957 }
13958 
13959 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
13961  SCIP_VAR* var, /**< problem variable */
13962  SCIP_STAT* stat, /**< problem statistics */
13963  SCIP_SET* set, /**< global SCIP settings */
13964  SCIP_Real solval /**< solution value, e.g., LP solution value */
13965  )
13966 {
13967  SCIP_Real upscore;
13968  SCIP_Real downscore;
13969  SCIP_Real solvaldeltaup;
13970  SCIP_Real solvaldeltadown;
13971 
13972  /* LP root estimate only works for variables with fractional LP root solution */
13973  if( SCIPsetIsFeasIntegral(set, solval) )
13974  return 0.0;
13975 
13976  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
13978  return 0.0;
13979 
13980  /* compute delta's to ceil and floor of root LP solution value */
13981  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
13982  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
13983 
13984 
13985  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
13986  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
13987 
13988  return MIN(upscore, downscore);
13989 }
13990 
13991 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
13993  SCIP_VAR* var, /**< problem variable */
13994  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
13995  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
13996  )
13997 {
13998  assert(var != NULL);
13999  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14000 
14001  switch( SCIPvarGetStatus(var) )
14002  {
14004  if( var->data.original.transvar == NULL )
14005  return 0.0;
14006  else
14007  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14008 
14009  case SCIP_VARSTATUS_LOOSE:
14010  case SCIP_VARSTATUS_COLUMN:
14011  if( onlycurrentrun )
14013  else
14014  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14015 
14016  case SCIP_VARSTATUS_FIXED:
14017  return 0.0;
14018 
14020  if( var->data.aggregate.scalar > 0.0 )
14021  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14022  else
14023  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14024 
14026  return 0.0;
14027 
14029  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14030 
14031  default:
14032  SCIPerrorMessage("unknown variable status\n");
14033  SCIPABORT();
14034  return 0.0; /*lint !e527*/
14035  }
14036 }
14037 
14038 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14039  *
14040  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14041  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14042  * of 2 * clevel - 1.
14043  *
14044  * @return value of confidence bound for this variable
14045  */
14047  SCIP_VAR* var, /**< variable in question */
14048  SCIP_SET* set, /**< global SCIP settings */
14049  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14050  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14051  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14052  )
14053 {
14054  SCIP_Real confidencebound;
14055 
14056  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14057  if( SCIPsetIsFeasPositive(set, confidencebound) )
14058  {
14059  SCIP_Real count;
14060 
14061  if( onlycurrentrun )
14062  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14063  else
14064  count = SCIPvarGetPseudocostCount(var, dir);
14065  /* assertion is valid because variance is positive */
14066  assert(count >= 1.9);
14067 
14068  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14069  confidencebound = sqrt(confidencebound);
14070 
14071  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14072  * the number of pseudo cost evaluations of this variable in the respective direction. */
14073  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14074  }
14075  else
14076  confidencebound = 0.0;
14077 
14078  return confidencebound;
14079 }
14080 
14081 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14082  * Error is calculated at a specific confidence level
14083  */
14085  SCIP_VAR* var, /**< variable in question */
14086  SCIP_SET* set, /**< global SCIP settings */
14087  SCIP_STAT* stat, /**< problem statistics */
14088  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14089  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14090  )
14091 {
14092  SCIP_Real downsize;
14093  SCIP_Real upsize;
14094  SCIP_Real size;
14095  SCIP_Real relerrorup;
14096  SCIP_Real relerrordown;
14097  SCIP_Real relerror;
14098 
14099  /* check, if the pseudo cost score of the variable is reliable */
14102  size = MIN(downsize, upsize);
14103 
14104  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14105  if( size <= 1.9 )
14106  return FALSE;
14107 
14108  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14109  * confidence interval bound at confidence level of 95% for individual variable reliability.
14110  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14111  */
14112  if( downsize >= 1.9 )
14113  {
14114  SCIP_Real normval;
14115 
14116  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14117  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14118  normval = MAX(1.0, normval);
14119 
14120  relerrordown /= normval;
14121  }
14122  else
14123  relerrordown = 0.0;
14124 
14125  if( upsize >= 1.9 )
14126  {
14127  SCIP_Real normval;
14128 
14129  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14130  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14131  normval = MAX(1.0, normval);
14132  relerrorup /= normval;
14133  }
14134  else
14135  relerrorup = 0.0;
14136 
14137  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14138  relerror = MAX(relerrorup, relerrordown);
14139 
14140  return (relerror <= threshold);
14141 }
14142 
14143 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14144  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14145  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14146  * unknown location means of the underlying pseudo-cost distributions of x and y.
14147  *
14148  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14149  * better than x (despite the current information), meaning that y can be expected to yield branching
14150  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14151  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14152  * than y.
14153  *
14154  * @note The order of x and y matters for the one-sided hypothesis
14155  *
14156  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14157  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14158  *
14159  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14160  */
14162  SCIP_SET* set, /**< global SCIP settings */
14163  SCIP_STAT* stat, /**< problem statistics */
14164  SCIP_VAR* varx, /**< variable x */
14165  SCIP_Real fracx, /**< the fractionality of variable x */
14166  SCIP_VAR* vary, /**< variable y */
14167  SCIP_Real fracy, /**< the fractionality of variable y */
14168  SCIP_BRANCHDIR dir, /**< branching direction */
14169  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14170  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14171  )
14172 {
14173  SCIP_Real meanx;
14174  SCIP_Real meany;
14175  SCIP_Real variancex;
14176  SCIP_Real variancey;
14177  SCIP_Real countx;
14178  SCIP_Real county;
14179  SCIP_Real tresult;
14180  SCIP_Real realdirection;
14181 
14182 
14183  if( varx == vary )
14184  return FALSE;
14185 
14186  countx = SCIPvarGetPseudocostCount(varx, dir);
14187  county = SCIPvarGetPseudocostCount(vary, dir);
14188 
14189  /* if not at least 2 measurements were taken, return FALSE */
14190  if( countx <= 1.9 || county <= 1.9 )
14191  return FALSE;
14192 
14193  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14194 
14195  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14196  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14197 
14198  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14199  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14200 
14201  /* if there is no variance, the means are taken from a constant distribution */
14202  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14203  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14204 
14205  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14206 
14207  /* for the two-sided hypothesis, just take the absolute of t */
14208  if( !onesided )
14209  tresult = REALABS(tresult);
14210 
14211  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14212 }
14213 
14214 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14215  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14216  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14217  * of at least \p threshold.
14218  *
14219  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14220  * the estimated probability to exceed \p threshold is less than 25 %.
14221  *
14222  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14223  * of confidence.
14224  *
14225  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14226  * at the given confidence level \p clevel.
14227  */
14229  SCIP_SET* set, /**< global SCIP settings */
14230  SCIP_STAT* stat, /**< problem statistics */
14231  SCIP_VAR* var, /**< variable x */
14232  SCIP_Real frac, /**< the fractionality of variable x */
14233  SCIP_Real threshold, /**< the threshold to test against */
14234  SCIP_BRANCHDIR dir, /**< branching direction */
14235  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14236  )
14237 {
14238  SCIP_Real mean;
14239  SCIP_Real variance;
14240  SCIP_Real count;
14241  SCIP_Real realdirection;
14242  SCIP_Real probability;
14243  SCIP_Real problimit;
14244 
14245  count = SCIPvarGetPseudocostCount(var, dir);
14246 
14247  /* if not at least 2 measurements were taken, return FALSE */
14248  if( count <= 1.9 )
14249  return FALSE;
14250 
14251  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14252 
14253  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14254  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14255 
14256  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14257  if( SCIPsetIsFeasGE(set, mean, threshold) )
14258  return FALSE;
14259 
14260  /* if there is no variance, the means are taken from a constant distribution */
14261  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14262  return SCIPsetIsFeasLT(set, mean, threshold);
14263 
14264  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14265  probability = SCIPnormalCDF(mean, variance, threshold);
14266 
14267  /* determine a probability limit corresponding to the given confidence level */
14268  switch( clevel )
14269  {
14271  problimit = 0.75;
14272  break;
14274  problimit = 0.875;
14275  break;
14277  problimit = 0.9;
14278  break;
14280  problimit = 0.95;
14281  break;
14283  problimit = 0.975;
14284  break;
14285  default:
14286  problimit = -1;
14287  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14288  SCIPABORT();
14289  break;
14290  }
14291 
14292  return (probability >= problimit);
14293 }
14294 
14295 /** find the corresponding history entry if already existing, otherwise create new entry */
14296 static
14298  SCIP_VAR* var, /**< problem variable */
14299  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14300  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14301  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14302  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14303  )
14304 {
14305  assert(var != NULL);
14306  assert(blkmem != NULL);
14307  assert(set != NULL);
14308  assert(history != NULL);
14309 
14310  (*history) = NULL;
14311 
14312  if( var->valuehistory == NULL )
14313  {
14314  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14315  }
14316 
14317  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14318 
14319  return SCIP_OKAY;
14320 }
14321 
14322 /** check if value based history should be used */
14323 static
14325  SCIP_VAR* var, /**< problem variable */
14326  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14327  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14328  )
14329 {
14330  /* check if the domain value is unknown (not specific) */
14331  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14332  return FALSE;
14333 
14334  assert(set != NULL);
14335 
14336  /* check if value based history should be collected */
14337  if( !set->history_valuebased )
14338  return FALSE;
14339 
14340  /* value based history is not collected for binary variable since the standard history already contains all information */
14341  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14342  return FALSE;
14343 
14344  /* value based history is not collected for continuous variables */
14346  return FALSE;
14347 
14348  return TRUE;
14349 }
14350 
14351 /** increases VSIDS of the variable by the given weight */
14353  SCIP_VAR* var, /**< problem variable */
14354  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14355  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14356  SCIP_STAT* stat, /**< problem statistics */
14357  SCIP_BRANCHDIR dir, /**< branching direction */
14358  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14359  SCIP_Real weight /**< weight of this update in VSIDS */
14360  )
14361 {
14362  assert(var != NULL);
14363  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14364 
14365  /* check if history statistics should be collected for a variable */
14366  if( !stat->collectvarhistory )
14367  return SCIP_OKAY;
14368 
14369  if( SCIPsetIsZero(set, weight) )
14370  return SCIP_OKAY;
14371 
14372  switch( SCIPvarGetStatus(var) )
14373  {
14375  if( var->data.original.transvar == NULL )
14376  {
14377  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14378  return SCIP_INVALIDDATA;
14379  }
14380  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14381  return SCIP_OKAY;
14382 
14383  case SCIP_VARSTATUS_LOOSE:
14384  case SCIP_VARSTATUS_COLUMN:
14385  {
14386  SCIPhistoryIncVSIDS(var->history, dir, weight);
14387  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14388 
14389  if( useValuehistory(var, value, set) )
14390  {
14391  SCIP_HISTORY* history;
14392 
14393  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14394  assert(history != NULL);
14395 
14396  SCIPhistoryIncVSIDS(history, dir, weight);
14397  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14398  value, weight, SCIPhistoryGetVSIDS(history, dir));
14399  }
14400 
14401  return SCIP_OKAY;
14402  }
14403  case SCIP_VARSTATUS_FIXED:
14404  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14405  return SCIP_INVALIDDATA;
14406 
14408  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14409 
14410  if( var->data.aggregate.scalar > 0.0 )
14411  {
14412  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14413  }
14414  else
14415  {
14416  assert(var->data.aggregate.scalar < 0.0);
14417  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14418  }
14419  return SCIP_OKAY;
14420 
14422  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14423  return SCIP_INVALIDDATA;
14424 
14426  value = 1.0 - value;
14427 
14428  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14429  return SCIP_OKAY;
14430 
14431  default:
14432  SCIPerrorMessage("unknown variable status\n");
14433  return SCIP_INVALIDDATA;
14434  }
14435 }
14436 
14437 /** scales the VSIDS of the variable by the given scalar */
14439  SCIP_VAR* var, /**< problem variable */
14440  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14441  )
14442 {
14443  assert(var != NULL);
14444 
14445  switch( SCIPvarGetStatus(var) )
14446  {
14448  if( var->data.original.transvar == NULL )
14449  {
14450  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14451  return SCIP_INVALIDDATA;
14452  }
14454  return SCIP_OKAY;
14455 
14456  case SCIP_VARSTATUS_LOOSE:
14457  case SCIP_VARSTATUS_COLUMN:
14458  {
14459  SCIPhistoryScaleVSIDS(var->history, scalar);
14460  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14462 
14463  return SCIP_OKAY;
14464  }
14465  case SCIP_VARSTATUS_FIXED:
14466  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14467  return SCIP_INVALIDDATA;
14468 
14470  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14471  return SCIP_OKAY;
14472 
14474  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14475  return SCIP_INVALIDDATA;
14476 
14478  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14479  return SCIP_OKAY;
14480 
14481  default:
14482  SCIPerrorMessage("unknown variable status\n");
14483  return SCIP_INVALIDDATA;
14484  }
14485 }
14486 
14487 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14489  SCIP_VAR* var, /**< problem variable */
14490  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14491  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14492  SCIP_STAT* stat, /**< problem statistics */
14493  SCIP_BRANCHDIR dir, /**< branching direction */
14494  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14495  SCIP_Real length /**< length of the conflict */
14496  )
14497 {
14498  assert(var != NULL);
14499  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14500 
14501  /* check if history statistics should be collected for a variable */
14502  if( !stat->collectvarhistory )
14503  return SCIP_OKAY;
14504 
14505  switch( SCIPvarGetStatus(var) )
14506  {
14508  if( var->data.original.transvar == NULL )
14509  {
14510  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14511  return SCIP_INVALIDDATA;
14512  }
14513  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14514  return SCIP_OKAY;
14515 
14516  case SCIP_VARSTATUS_LOOSE:
14517  case SCIP_VARSTATUS_COLUMN:
14518  {
14519  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14520  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14521 
14522  if( useValuehistory(var, value, set) )
14523  {
14524  SCIP_HISTORY* history;
14525 
14526  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14527  assert(history != NULL);
14528 
14529  SCIPhistoryIncNActiveConflicts(history, dir, length);
14530  }
14531 
14532  return SCIP_OKAY;
14533  }
14534  case SCIP_VARSTATUS_FIXED:
14535  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14536  return SCIP_INVALIDDATA;
14537 
14539  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14540 
14541  if( var->data.aggregate.scalar > 0.0 )
14542  {
14543  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14544  }
14545  else
14546  {
14547  assert(var->data.aggregate.scalar < 0.0);
14548  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14549  }
14550  return SCIP_OKAY;
14551 
14553  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14554  return SCIP_INVALIDDATA;
14555 
14557  value = 1.0 - value;
14558 
14559  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14560  return SCIP_OKAY;
14561 
14562  default:
14563  SCIPerrorMessage("unknown variable status\n");
14564  return SCIP_INVALIDDATA;
14565  }
14566 }
14567 
14568 /** gets the number of active conflicts containing this variable in given direction */
14570  SCIP_VAR* var, /**< problem variable */
14571  SCIP_STAT* stat, /**< problem statistics */
14572  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14573  )
14574 {
14575  assert(var != NULL);
14576  assert(stat != NULL);
14577  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14578 
14579  switch( SCIPvarGetStatus(var) )
14580  {
14582  if( var->data.original.transvar == NULL )
14583  return 0;
14584  else
14585  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14586 
14587  case SCIP_VARSTATUS_LOOSE:
14588  case SCIP_VARSTATUS_COLUMN:
14589  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14590 
14591  case SCIP_VARSTATUS_FIXED:
14592  return 0;
14593 
14595  if( var->data.aggregate.scalar > 0.0 )
14596  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14597  else
14599 
14601  return 0;
14602 
14605 
14606  default:
14607  SCIPerrorMessage("unknown variable status\n");
14608  SCIPABORT();
14609  return 0; /*lint !e527*/
14610  }
14611 }
14612 
14613 /** gets the number of active conflicts containing this variable in given direction
14614  * in the current run
14615  */
14617  SCIP_VAR* var, /**< problem variable */
14618  SCIP_STAT* stat, /**< problem statistics */
14619  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14620  )
14621 {
14622  assert(var != NULL);
14623  assert(stat != NULL);
14624  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14625 
14626  switch( SCIPvarGetStatus(var) )
14627  {
14629  if( var->data.original.transvar == NULL )
14630  return 0;
14631  else
14633 
14634  case SCIP_VARSTATUS_LOOSE:
14635  case SCIP_VARSTATUS_COLUMN:
14636  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14637 
14638  case SCIP_VARSTATUS_FIXED:
14639  return 0;
14640 
14642  if( var->data.aggregate.scalar > 0.0 )
14643  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14644  else
14646 
14648  return 0;
14649 
14652 
14653  default:
14654  SCIPerrorMessage("unknown variable status\n");
14655  SCIPABORT();
14656  return 0; /*lint !e527*/
14657  }
14658 }
14659 
14660 /** gets the average conflict length in given direction due to branching on the variable */
14662  SCIP_VAR* var, /**< problem variable */
14663  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14664  )
14665 {
14666  assert(var != NULL);
14667  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14668 
14669  switch( SCIPvarGetStatus(var) )
14670  {
14672  if( var->data.original.transvar == NULL )
14673  return 0.0;
14674  else
14676 
14677  case SCIP_VARSTATUS_LOOSE:
14678  case SCIP_VARSTATUS_COLUMN:
14679  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14680  case SCIP_VARSTATUS_FIXED:
14681  return 0.0;
14682 
14684  if( var->data.aggregate.scalar > 0.0 )
14685  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14686  else
14688 
14690  return 0.0;
14691 
14694 
14695  default:
14696  SCIPerrorMessage("unknown variable status\n");
14697  SCIPABORT();
14698  return 0.0; /*lint !e527*/
14699  }
14700 }
14701 
14702 /** gets the average conflict length in given direction due to branching on the variable
14703  * in the current run
14704  */
14706  SCIP_VAR* var, /**< problem variable */
14707  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14708  )
14709 {
14710  assert(var != NULL);
14711  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14712 
14713  switch( SCIPvarGetStatus(var) )
14714  {
14716  if( var->data.original.transvar == NULL )
14717  return 0.0;
14718  else
14720 
14721  case SCIP_VARSTATUS_LOOSE:
14722  case SCIP_VARSTATUS_COLUMN:
14723  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14724 
14725  case SCIP_VARSTATUS_FIXED:
14726  return 0.0;
14727 
14729  if( var->data.aggregate.scalar > 0.0 )
14731  else
14733 
14735  return 0.0;
14736 
14739 
14740  default:
14741  SCIPerrorMessage("unknown variable status\n");
14742  SCIPABORT();
14743  return 0.0; /*lint !e527*/
14744  }
14745 }
14746 
14747 /** increases the number of branchings counter of the variable */
14749  SCIP_VAR* var, /**< problem variable */
14750  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14751  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14752  SCIP_STAT* stat, /**< problem statistics */
14753  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14754  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14755  int depth /**< depth at which the bound change took place */
14756  )
14757 {
14758  assert(var != NULL);
14759  assert(stat != NULL);
14760  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14761 
14762  /* check if history statistics should be collected for a variable */
14763  if( !stat->collectvarhistory )
14764  return SCIP_OKAY;
14765 
14766  switch( SCIPvarGetStatus(var) )
14767  {
14769  if( var->data.original.transvar == NULL )
14770  {
14771  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14772  return SCIP_INVALIDDATA;
14773  }
14774  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14775  return SCIP_OKAY;
14776 
14777  case SCIP_VARSTATUS_LOOSE:
14778  case SCIP_VARSTATUS_COLUMN:
14779  {
14780  SCIPhistoryIncNBranchings(var->history, dir, depth);
14781  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14782  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14783  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14784 
14785  if( useValuehistory(var, value, set) )
14786  {
14787  SCIP_HISTORY* history;
14788 
14789  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14790  assert(history != NULL);
14791 
14792  SCIPhistoryIncNBranchings(history, dir, depth);
14793  }
14794 
14795  return SCIP_OKAY;
14796  }
14797  case SCIP_VARSTATUS_FIXED:
14798  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14799  return SCIP_INVALIDDATA;
14800 
14802  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14803 
14804  if( var->data.aggregate.scalar > 0.0 )
14805  {
14806  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14807  }
14808  else
14809  {
14810  assert(var->data.aggregate.scalar < 0.0);
14811  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14812  }
14813  return SCIP_OKAY;
14814 
14816  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14817  return SCIP_INVALIDDATA;
14818 
14820  value = 1.0 - value;
14821 
14822  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14823  return SCIP_OKAY;
14824 
14825  default:
14826  SCIPerrorMessage("unknown variable status\n");
14827  return SCIP_INVALIDDATA;
14828  }
14829 }
14830 
14831 /** increases the inference sum of the variable by the given weight */
14833  SCIP_VAR* var, /**< problem variable */
14834  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14835  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14836  SCIP_STAT* stat, /**< problem statistics */
14837  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14838  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14839  SCIP_Real weight /**< weight of this update in inference score */
14840  )
14841 {
14842  assert(var != NULL);
14843  assert(stat != NULL);
14844  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14845 
14846  /* check if history statistics should be collected for a variable */
14847  if( !stat->collectvarhistory )
14848  return SCIP_OKAY;
14849 
14850  switch( SCIPvarGetStatus(var) )
14851  {
14853  if( var->data.original.transvar == NULL )
14854  {
14855  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
14856  return SCIP_INVALIDDATA;
14857  }
14858  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14859  return SCIP_OKAY;
14860 
14861  case SCIP_VARSTATUS_LOOSE:
14862  case SCIP_VARSTATUS_COLUMN:
14863  {
14864  SCIPhistoryIncInferenceSum(var->history, dir, weight);
14865  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
14866  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
14867  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
14868 
14869  if( useValuehistory(var, value, set) )
14870  {
14871  SCIP_HISTORY* history;
14872 
14873  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14874  assert(history != NULL);
14875 
14876  SCIPhistoryIncInferenceSum(history, dir, weight);
14877  }
14878 
14879  return SCIP_OKAY;
14880  }
14881  case SCIP_VARSTATUS_FIXED:
14882  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
14883  return SCIP_INVALIDDATA;
14884 
14886  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14887 
14888  if( var->data.aggregate.scalar > 0.0 )
14889  {
14890  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14891  }
14892  else
14893  {
14894  assert(var->data.aggregate.scalar < 0.0);
14895  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14896  }
14897  return SCIP_OKAY;
14898 
14900  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
14901  return SCIP_INVALIDDATA;
14902 
14904  value = 1.0 - value;
14905 
14906  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14907  return SCIP_OKAY;
14908 
14909  default:
14910  SCIPerrorMessage("unknown variable status\n");
14911  return SCIP_INVALIDDATA;
14912  }
14913 }
14914 
14915 /** increases the cutoff sum of the variable by the given weight */
14917  SCIP_VAR* var, /**< problem variable */
14918  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14919  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14920  SCIP_STAT* stat, /**< problem statistics */
14921  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14922  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14923  SCIP_Real weight /**< weight of this update in cutoff score */
14924  )
14925 {
14926  assert(var != NULL);
14927  assert(stat != NULL);
14928  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14929 
14930  /* check if history statistics should be collected for a variable */
14931  if( !stat->collectvarhistory )
14932  return SCIP_OKAY;
14933 
14934  switch( SCIPvarGetStatus(var) )
14935  {
14937  if( var->data.original.transvar == NULL )
14938  {
14939  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
14940  return SCIP_INVALIDDATA;
14941  }
14942  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14943  return SCIP_OKAY;
14944 
14945  case SCIP_VARSTATUS_LOOSE:
14946  case SCIP_VARSTATUS_COLUMN:
14947  {
14948  SCIPhistoryIncCutoffSum(var->history, dir, weight);
14949  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
14950  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
14951  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
14952 
14953  if( useValuehistory(var, value, set) )
14954  {
14955  SCIP_HISTORY* history;
14956 
14957  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14958  assert(history != NULL);
14959 
14960  SCIPhistoryIncCutoffSum(history, dir, weight);
14961  }
14962 
14963  return SCIP_OKAY;
14964  }
14965  case SCIP_VARSTATUS_FIXED:
14966  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
14967  return SCIP_INVALIDDATA;
14968 
14970  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14971 
14972  if( var->data.aggregate.scalar > 0.0 )
14973  {
14974  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14975  }
14976  else
14977  {
14978  assert(var->data.aggregate.scalar < 0.0);
14979  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14980  }
14981  return SCIP_OKAY;
14982 
14984  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
14985  return SCIP_INVALIDDATA;
14986 
14988  value = 1.0 - value;
14989 
14990  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14991  return SCIP_OKAY;
14992 
14993  default:
14994  SCIPerrorMessage("unknown variable status\n");
14995  return SCIP_INVALIDDATA;
14996  }
14997 }
14998 
14999 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15001  SCIP_VAR* var, /**< problem variable */
15002  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15003  )
15004 {
15005  assert(var != NULL);
15006  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15007 
15008  switch( SCIPvarGetStatus(var) )
15009  {
15011  if( var->data.original.transvar == NULL )
15012  return 0;
15013  else
15014  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15015 
15016  case SCIP_VARSTATUS_LOOSE:
15017  case SCIP_VARSTATUS_COLUMN:
15018  return SCIPhistoryGetNBranchings(var->history, dir);
15019 
15020  case SCIP_VARSTATUS_FIXED:
15021  return 0;
15022 
15024  if( var->data.aggregate.scalar > 0.0 )
15025  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15026  else
15028 
15030  return 0;
15031 
15034 
15035  default:
15036  SCIPerrorMessage("unknown variable status\n");
15037  SCIPABORT();
15038  return 0; /*lint !e527*/
15039  }
15040 }
15041 
15042 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15043  * in the current run
15044  */
15046  SCIP_VAR* var, /**< problem variable */
15047  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15048  )
15049 {
15050  assert(var != NULL);
15051  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15052 
15053  switch( SCIPvarGetStatus(var) )
15054  {
15056  if( var->data.original.transvar == NULL )
15057  return 0;
15058  else
15060 
15061  case SCIP_VARSTATUS_LOOSE:
15062  case SCIP_VARSTATUS_COLUMN:
15063  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15064 
15065  case SCIP_VARSTATUS_FIXED:
15066  return 0;
15067 
15069  if( var->data.aggregate.scalar > 0.0 )
15071  else
15073 
15075  return 0;
15076 
15079 
15080  default:
15081  SCIPerrorMessage("unknown variable status\n");
15082  SCIPABORT();
15083  return 0; /*lint !e527*/
15084  }
15085 }
15086 
15087 /** returns the average depth of bound changes in given direction due to branching on the variable */
15089  SCIP_VAR* var, /**< problem variable */
15090  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15091  )
15092 {
15093  assert(var != NULL);
15094  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15095 
15096  switch( SCIPvarGetStatus(var) )
15097  {
15099  if( var->data.original.transvar == NULL )
15100  return 0.0;
15101  else
15102  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15103 
15104  case SCIP_VARSTATUS_LOOSE:
15105  case SCIP_VARSTATUS_COLUMN:
15106  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15107 
15108  case SCIP_VARSTATUS_FIXED:
15109  return 0.0;
15110 
15112  if( var->data.aggregate.scalar > 0.0 )
15113  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15114  else
15116 
15118  return 0.0;
15119 
15122 
15123  default:
15124  SCIPerrorMessage("unknown variable status\n");
15125  SCIPABORT();
15126  return 0.0; /*lint !e527*/
15127  }
15128 }
15129 
15130 /** returns the average depth of bound changes in given direction due to branching on the variable
15131  * in the current run
15132  */
15134  SCIP_VAR* var, /**< problem variable */
15135  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15136  )
15137 {
15138  assert(var != NULL);
15139  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15140 
15141  switch( SCIPvarGetStatus(var) )
15142  {
15144  if( var->data.original.transvar == NULL )
15145  return 0.0;
15146  else
15148 
15149  case SCIP_VARSTATUS_LOOSE:
15150  case SCIP_VARSTATUS_COLUMN:
15151  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15152 
15153  case SCIP_VARSTATUS_FIXED:
15154  return 0.0;
15155 
15157  if( var->data.aggregate.scalar > 0.0 )
15159  else
15162 
15164  return 0.0;
15165 
15168  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15169 
15170  default:
15171  SCIPerrorMessage("unknown variable status\n");
15172  SCIPABORT();
15173  return 0.0; /*lint !e527*/
15174  }
15175 }
15176 
15177 /** returns the variable's VSIDS score */
15179  SCIP_VAR* var, /**< problem variable */
15180  SCIP_STAT* stat, /**< problem statistics */
15181  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15182  )
15183 {
15184  assert(var != NULL);
15185  assert(stat != NULL);
15186  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15187 
15189  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15190 
15191  switch( SCIPvarGetStatus(var) )
15192  {
15194  if( var->data.original.transvar == NULL )
15195  return 0.0;
15196  else
15197  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15198 
15199  case SCIP_VARSTATUS_LOOSE:
15200  case SCIP_VARSTATUS_COLUMN:
15201  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15202  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15203 
15204  case SCIP_VARSTATUS_FIXED:
15205  return 0.0;
15206 
15208  if( var->data.aggregate.scalar > 0.0 )
15209  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15210  else
15211  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15212 
15214  return 0.0;
15215 
15217  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15218 
15219  default:
15220  SCIPerrorMessage("unknown variable status\n");
15221  SCIPABORT();
15222  return 0.0; /*lint !e527*/
15223  }
15224 }
15225 
15226 /** returns the variable's VSIDS score only using conflicts of the current run */
15228  SCIP_VAR* var, /**< problem variable */
15229  SCIP_STAT* stat, /**< problem statistics */
15230  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15231  )
15232 {
15233  assert(var != NULL);
15234  assert(stat != NULL);
15235  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15236 
15237  switch( SCIPvarGetStatus(var) )
15238  {
15240  if( var->data.original.transvar == NULL )
15241  return 0.0;
15242  else
15243  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15244 
15245  case SCIP_VARSTATUS_LOOSE:
15246  case SCIP_VARSTATUS_COLUMN:
15247  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15248 
15249  case SCIP_VARSTATUS_FIXED:
15250  return 0.0;
15251 
15253  if( var->data.aggregate.scalar > 0.0 )
15254  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15255  else
15257 
15259  return 0.0;
15260 
15263 
15264  default:
15265  SCIPerrorMessage("unknown variable status\n");
15266  SCIPABORT();
15267  return 0.0; /*lint !e527*/
15268  }
15269 }
15270 
15271 /** returns the number of inferences branching on this variable in given direction triggered */
15273  SCIP_VAR* var, /**< problem variable */
15274  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15275  )
15276 {
15277  assert(var != NULL);
15278  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15279 
15280  switch( SCIPvarGetStatus(var) )
15281  {
15283  if( var->data.original.transvar == NULL )
15284  return 0.0;
15285  else
15286  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15287 
15288  case SCIP_VARSTATUS_LOOSE:
15289  case SCIP_VARSTATUS_COLUMN:
15290  return SCIPhistoryGetInferenceSum(var->history, dir);
15291 
15292  case SCIP_VARSTATUS_FIXED:
15293  return 0.0;
15294 
15296  if( var->data.aggregate.scalar > 0.0 )
15297  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15298  else
15300 
15302  return 0.0;
15303 
15306 
15307  default:
15308  SCIPerrorMessage("unknown variable status\n");
15309  SCIPABORT();
15310  return 0.0; /*lint !e527*/
15311  }
15312 }
15313 
15314 /** returns the number of inferences branching on this variable in given direction triggered
15315  * in the current run
15316  */
15318  SCIP_VAR* var, /**< problem variable */
15319  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15320  )
15321 {
15322  assert(var != NULL);
15323  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15324 
15325  switch( SCIPvarGetStatus(var) )
15326  {
15328  if( var->data.original.transvar == NULL )
15329  return 0.0;
15330  else
15332 
15333  case SCIP_VARSTATUS_LOOSE:
15334  case SCIP_VARSTATUS_COLUMN:
15335  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15336 
15337  case SCIP_VARSTATUS_FIXED:
15338  return 0.0;
15339 
15341  if( var->data.aggregate.scalar > 0.0 )
15343  else
15345 
15347  return 0.0;
15348 
15351 
15352  default:
15353  SCIPerrorMessage("unknown variable status\n");
15354  SCIPABORT();
15355  return 0.0; /*lint !e527*/
15356  }
15357 }
15358 
15359 /** returns the average number of inferences found after branching on the variable in given direction */
15361  SCIP_VAR* var, /**< problem variable */
15362  SCIP_STAT* stat, /**< problem statistics */
15363  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15364  )
15365 {
15366  assert(var != NULL);
15367  assert(stat != NULL);
15368  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15369 
15370  switch( SCIPvarGetStatus(var) )
15371  {
15373  if( var->data.original.transvar == NULL )
15374  return SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15375  else
15376  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15377 
15378  case SCIP_VARSTATUS_LOOSE:
15379  case SCIP_VARSTATUS_COLUMN:
15380  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15381  return SCIPhistoryGetAvgInferences(var->history, dir);
15382  else
15383  {
15384  int nimpls;
15385  int ncliques;
15386 
15387  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15388  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15389  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15390  }
15391 
15392  case SCIP_VARSTATUS_FIXED:
15393  return 0.0;
15394 
15396  if( var->data.aggregate.scalar > 0.0 )
15397  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15398  else
15400 
15402  return 0.0;
15403 
15405  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15406 
15407  default:
15408  SCIPerrorMessage("unknown variable status\n");
15409  SCIPABORT();
15410  return 0.0; /*lint !e527*/
15411  }
15412 }
15413 
15414 /** returns the average number of inferences found after branching on the variable in given direction
15415  * in the current run
15416  */
15418  SCIP_VAR* var, /**< problem variable */
15419  SCIP_STAT* stat, /**< problem statistics */
15420  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15421  )
15422 {
15423  assert(var != NULL);
15424  assert(stat != NULL);
15425  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15426 
15427  switch( SCIPvarGetStatus(var) )
15428  {
15430  if( var->data.original.transvar == NULL )
15431  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15432  else
15433  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15434 
15435  case SCIP_VARSTATUS_LOOSE:
15436  case SCIP_VARSTATUS_COLUMN:
15437  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15438  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15439  else
15440  {
15441  int nimpls;
15442  int ncliques;
15443 
15444  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15445  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15446  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15447  }
15448 
15449  case SCIP_VARSTATUS_FIXED:
15450  return 0.0;
15451 
15453  if( var->data.aggregate.scalar > 0.0 )
15454  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15455  else
15457 
15459  return 0.0;
15460 
15463 
15464  default:
15465  SCIPerrorMessage("unknown variable status\n");
15466  SCIPABORT();
15467  return 0.0; /*lint !e527*/
15468  }
15469 }
15470 
15471 /** returns the number of cutoffs branching on this variable in given direction produced */
15473  SCIP_VAR* var, /**< problem variable */
15474  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15475  )
15476 {
15477  assert(var != NULL);
15478  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15479 
15480  switch( SCIPvarGetStatus(var) )
15481  {
15483  if( var->data.original.transvar == NULL )
15484  return 0;
15485  else
15486  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15487 
15488  case SCIP_VARSTATUS_LOOSE:
15489  case SCIP_VARSTATUS_COLUMN:
15490  return SCIPhistoryGetCutoffSum(var->history, dir);
15491 
15492  case SCIP_VARSTATUS_FIXED:
15493  return 0;
15494 
15496  if( var->data.aggregate.scalar > 0.0 )
15497  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15498  else
15500 
15502  return 0;
15503 
15506 
15507  default:
15508  SCIPerrorMessage("unknown variable status\n");
15509  SCIPABORT();
15510  return 0; /*lint !e527*/
15511  }
15512 }
15513 
15514 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15516  SCIP_VAR* var, /**< problem variable */
15517  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15518  )
15519 {
15520  assert(var != NULL);
15521  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15522 
15523  switch( SCIPvarGetStatus(var) )
15524  {
15526  if( var->data.original.transvar == NULL )
15527  return 0;
15528  else
15530 
15531  case SCIP_VARSTATUS_LOOSE:
15532  case SCIP_VARSTATUS_COLUMN:
15533  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15534 
15535  case SCIP_VARSTATUS_FIXED:
15536  return 0;
15537 
15539  if( var->data.aggregate.scalar > 0.0 )
15540  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15541  else
15543 
15545  return 0;
15546 
15549 
15550  default:
15551  SCIPerrorMessage("unknown variable status\n");
15552  SCIPABORT();
15553  return 0; /*lint !e527*/
15554  }
15555 }
15556 
15557 /** returns the average number of cutoffs found after branching on the variable in given direction */
15559  SCIP_VAR* var, /**< problem variable */
15560  SCIP_STAT* stat, /**< problem statistics */
15561  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15562  )
15563 {
15564  assert(var != NULL);
15565  assert(stat != NULL);
15566  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15567 
15568  switch( SCIPvarGetStatus(var) )
15569  {
15571  if( var->data.original.transvar == NULL )
15572  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15573  else
15574  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15575 
15576  case SCIP_VARSTATUS_LOOSE:
15577  case SCIP_VARSTATUS_COLUMN:
15578  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15579  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15580  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15581 
15582  case SCIP_VARSTATUS_FIXED:
15583  return 0.0;
15584 
15586  if( var->data.aggregate.scalar > 0.0 )
15587  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15588  else
15589  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15590 
15592  return 0.0;
15593 
15595  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15596 
15597  default:
15598  SCIPerrorMessage("unknown variable status\n");
15599  SCIPABORT();
15600  return 0.0; /*lint !e527*/
15601  }
15602 }
15603 
15604 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15606  SCIP_VAR* var, /**< problem variable */
15607  SCIP_STAT* stat, /**< problem statistics */
15608  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15609  )
15610 {
15611  assert(var != NULL);
15612  assert(stat != NULL);
15613  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15614 
15615  switch( SCIPvarGetStatus(var) )
15616  {
15618  if( var->data.original.transvar == NULL )
15619  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15620  else
15621  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15622 
15623  case SCIP_VARSTATUS_LOOSE:
15624  case SCIP_VARSTATUS_COLUMN:
15625  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15628 
15629  case SCIP_VARSTATUS_FIXED:
15630  return 0.0;
15631 
15633  if( var->data.aggregate.scalar > 0.0 )
15634  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15635  else
15637 
15639  return 0.0;
15640 
15643 
15644  default:
15645  SCIPerrorMessage("unknown variable status\n");
15646  SCIPABORT();
15647  return 0.0; /*lint !e527*/
15648  }
15649 }
15650 
15651 
15652 
15653 
15654 /*
15655  * information methods for bound changes
15656  */
15657 
15658 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15660  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15661  BMS_BLKMEM* blkmem, /**< block memory */
15662  SCIP_VAR* var, /**< active variable that changed the bounds */
15663  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15664  SCIP_Real oldbound, /**< old value for bound */
15665  SCIP_Real newbound /**< new value for bound */
15666  )
15667 {
15668  assert(bdchginfo != NULL);
15669 
15670  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15671  (*bdchginfo)->oldbound = oldbound;
15672  (*bdchginfo)->newbound = newbound;
15673  (*bdchginfo)->var = var;
15674  (*bdchginfo)->inferencedata.var = var;
15675  (*bdchginfo)->inferencedata.reason.prop = NULL;
15676  (*bdchginfo)->inferencedata.info = 0;
15677  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15678  (*bdchginfo)->bdchgidx.pos = -1;
15679  (*bdchginfo)->pos = 0;
15680  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15681  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15682  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15683  (*bdchginfo)->redundant = FALSE;
15684 
15685  return SCIP_OKAY;
15686 }
15687 
15688 /** frees a bound change information object */
15689 void SCIPbdchginfoFree(
15690  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15691  BMS_BLKMEM* blkmem /**< block memory */
15692  )
15693 {
15694  assert(bdchginfo != NULL);
15695 
15696  BMSfreeBlockMemory(blkmem, bdchginfo);
15697 }
15698 
15699 /** returns the bound change information for the last lower bound change on given active problem variable before or
15700  * after the bound change with the given index was applied;
15701  * returns NULL, if no change to the lower bound was applied up to this point of time
15702  */
15704  SCIP_VAR* var, /**< active problem variable */
15705  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15706  SCIP_Bool after /**< should the bound change with given index be included? */
15707  )
15708 {
15709  int i;
15710 
15711  assert(var != NULL);
15712  assert(SCIPvarIsActive(var));
15713 
15714  /* search the correct bound change information for the given bound change index */
15715  if( after )
15716  {
15717  for( i = var->nlbchginfos-1; i >= 0; --i )
15718  {
15719  assert(var->lbchginfos[i].var == var);
15721  assert(var->lbchginfos[i].pos == i);
15722 
15723  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15724  if( var->lbchginfos[i].redundant )
15725  return NULL;
15726  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15727 
15728  /* if we reached the bound change index, return the current bound change info */
15729  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15730  return &var->lbchginfos[i];
15731  }
15732  }
15733  else
15734  {
15735  for( i = var->nlbchginfos-1; i >= 0; --i )
15736  {
15737  assert(var->lbchginfos[i].var == var);
15739  assert(var->lbchginfos[i].pos == i);
15740 
15741  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15742  if( var->lbchginfos[i].redundant )
15743  return NULL;
15744  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15745 
15746  /* if we reached the bound change index, return the current bound change info */
15747  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15748  return &var->lbchginfos[i];
15749  }
15750  }
15751 
15752  return NULL;
15753 }
15754 
15755 /** returns the bound change information for the last upper bound change on given active problem variable before or
15756  * after the bound change with the given index was applied;
15757  * returns NULL, if no change to the upper bound was applied up to this point of time
15758  */
15760  SCIP_VAR* var, /**< active problem variable */
15761  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15762  SCIP_Bool after /**< should the bound change with given index be included? */
15763  )
15764 {
15765  int i;
15766 
15767  assert(var != NULL);
15768  assert(SCIPvarIsActive(var));
15769 
15770  /* search the correct bound change information for the given bound change index */
15771  if( after )
15772  {
15773  for( i = var->nubchginfos-1; i >= 0; --i )
15774  {
15775  assert(var->ubchginfos[i].var == var);
15777  assert(var->ubchginfos[i].pos == i);
15778 
15779  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15780  if( var->ubchginfos[i].redundant )
15781  return NULL;
15782  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15783 
15784  /* if we reached the bound change index, return the current bound change info */
15785  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15786  return &var->ubchginfos[i];
15787  }
15788  }
15789  else
15790  {
15791  for( i = var->nubchginfos-1; i >= 0; --i )
15792  {
15793  assert(var->ubchginfos[i].var == var);
15795  assert(var->ubchginfos[i].pos == i);
15796 
15797  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15798  if( var->ubchginfos[i].redundant )
15799  return NULL;
15800  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15801 
15802  /* if we reached the bound change index, return the current bound change info */
15803  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15804  return &var->ubchginfos[i];
15805  }
15806  }
15807 
15808  return NULL;
15809 }
15810 
15811 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15812  * before or after the bound change with the given index was applied;
15813  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15814  */
15816  SCIP_VAR* var, /**< active problem variable */
15817  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15818  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15819  SCIP_Bool after /**< should the bound change with given index be included? */
15820  )
15821 {
15822  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15823  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
15824  else
15825  {
15826  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15827  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
15828  }
15829 }
15830 
15831 /** returns lower bound of variable directly before or after the bound change given by the bound change index
15832  * was applied
15833  *
15834  * @deprecated Please use SCIPgetVarLbAtIndex()
15835  */
15837  SCIP_VAR* var, /**< problem variable */
15838  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15839  SCIP_Bool after /**< should the bound change with given index be included? */
15840  )
15841 {
15842  SCIP_VARSTATUS varstatus;
15843  assert(var != NULL);
15844 
15845  varstatus = SCIPvarGetStatus(var);
15846 
15847  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15848  {
15849  if( bdchgidx == NULL )
15850  return SCIPvarGetLbLocal(var);
15851  else
15852  {
15853  SCIP_BDCHGINFO* bdchginfo;
15854 
15855  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
15856  if( bdchginfo != NULL )
15857  return SCIPbdchginfoGetNewbound(bdchginfo);
15858  else
15859  return var->glbdom.lb;
15860  }
15861  }
15862 
15863  /* get bounds of attached variables */
15864  switch( varstatus )
15865  {
15867  assert(var->data.original.transvar != NULL);
15868  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
15869 
15870  case SCIP_VARSTATUS_FIXED:
15871  return var->glbdom.lb;
15872 
15873  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15874  assert(var->data.aggregate.var != NULL);
15875  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15876  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15877  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15878  * (or is called by) a public interface method; instead, we only assert that values are finite
15879  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15880  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15881  */
15882  if( var->data.aggregate.scalar > 0.0 )
15883  {
15884  /* a > 0 -> get lower bound of y */
15885  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15886  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15887  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15888  + var->data.aggregate.constant;
15889  }
15890  else if( var->data.aggregate.scalar < 0.0 )
15891  {
15892  /* a < 0 -> get upper bound of y */
15893  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15894  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15895  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
15896  + var->data.aggregate.constant;
15897  }
15898  else
15899  {
15900  SCIPerrorMessage("scalar is zero in aggregation\n");
15901  SCIPABORT();
15902  return SCIP_INVALID; /*lint !e527*/
15903  }
15904 
15906  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
15907  if ( var->data.multaggr.nvars == 1 )
15908  {
15909  assert(var->data.multaggr.vars != NULL);
15910  assert(var->data.multaggr.scalars != NULL);
15911  assert(var->data.multaggr.vars[0] != NULL);
15912 
15913  if( var->data.multaggr.scalars[0] > 0.0 )
15914  {
15915  /* a > 0 -> get lower bound of y */
15916  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15917  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15918  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15919  + var->data.multaggr.constant;
15920  }
15921  else if( var->data.multaggr.scalars[0] < 0.0 )
15922  {
15923  /* a < 0 -> get upper bound of y */
15924  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15925  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15926  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
15927  + var->data.multaggr.constant;
15928  }
15929  else
15930  {
15931  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
15932  SCIPABORT();
15933  return SCIP_INVALID; /*lint !e527*/
15934  }
15935  }
15936  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
15937  SCIPABORT();
15938  return SCIP_INVALID; /*lint !e527*/
15939 
15940  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
15941  assert(var->negatedvar != NULL);
15943  assert(var->negatedvar->negatedvar == var);
15944  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
15945 
15946  case SCIP_VARSTATUS_COLUMN: /* for lint */
15947  case SCIP_VARSTATUS_LOOSE: /* for lint */
15948  default:
15949  SCIPerrorMessage("unknown variable status\n");
15950  SCIPABORT();
15951  return SCIP_INVALID; /*lint !e527*/
15952  }
15953 }
15954 
15955 /** returns upper bound of variable directly before or after the bound change given by the bound change index
15956  * was applied
15957  *
15958  * @deprecated Please use SCIPgetVarUbAtIndex()
15959  */
15961  SCIP_VAR* var, /**< problem variable */
15962  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15963  SCIP_Bool after /**< should the bound change with given index be included? */
15964  )
15965 {
15966  SCIP_VARSTATUS varstatus;
15967  assert(var != NULL);
15968 
15969  varstatus = SCIPvarGetStatus(var);
15970 
15971  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15972  {
15973  if( bdchgidx == NULL )
15974  return SCIPvarGetUbLocal(var);
15975  else
15976  {
15977  SCIP_BDCHGINFO* bdchginfo;
15978 
15979  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
15980  if( bdchginfo != NULL )
15981  return SCIPbdchginfoGetNewbound(bdchginfo);
15982  else
15983  return var->glbdom.ub;
15984  }
15985  }
15986 
15987  /* get bounds of attached variables */
15988  switch( varstatus )
15989  {
15991  assert(var->data.original.transvar != NULL);
15992  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
15993 
15994  case SCIP_VARSTATUS_FIXED:
15995  return var->glbdom.ub;
15996 
15997  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15998  assert(var->data.aggregate.var != NULL);
15999  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16000  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16001  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16002  * (or is called by) a public interface method; instead, we only assert that values are finite
16003  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16004  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16005  */
16006  if( var->data.aggregate.scalar > 0.0 )
16007  {
16008  /* a > 0 -> get lower bound of y */
16009  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16010  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16011  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16012  + var->data.aggregate.constant;
16013  }
16014  else if( var->data.aggregate.scalar < 0.0 )
16015  {
16016  /* a < 0 -> get upper bound of y */
16017  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16018  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16019  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16020  + var->data.aggregate.constant;
16021  }
16022  else
16023  {
16024  SCIPerrorMessage("scalar is zero in aggregation\n");
16025  SCIPABORT();
16026  return SCIP_INVALID; /*lint !e527*/
16027  }
16028 
16030  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16031  if ( var->data.multaggr.nvars == 1 )
16032  {
16033  assert(var->data.multaggr.vars != NULL);
16034  assert(var->data.multaggr.scalars != NULL);
16035  assert(var->data.multaggr.vars[0] != NULL);
16036 
16037  if( var->data.multaggr.scalars[0] > 0.0 )
16038  {
16039  /* a > 0 -> get lower bound of y */
16040  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16041  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16042  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16043  + var->data.multaggr.constant;
16044  }
16045  else if( var->data.multaggr.scalars[0] < 0.0 )
16046  {
16047  /* a < 0 -> get upper bound of y */
16048  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16049  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16050  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16051  + var->data.multaggr.constant;
16052  }
16053  else
16054  {
16055  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16056  SCIPABORT();
16057  return SCIP_INVALID; /*lint !e527*/
16058  }
16059  }
16060  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16061  SCIPABORT();
16062  return SCIP_INVALID; /*lint !e527*/
16063 
16064  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16065  assert(var->negatedvar != NULL);
16067  assert(var->negatedvar->negatedvar == var);
16068  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16069 
16070  case SCIP_VARSTATUS_COLUMN: /* for lint */
16071  case SCIP_VARSTATUS_LOOSE: /* for lint */
16072  default:
16073  SCIPerrorMessage("unknown variable status\n");
16074  SCIPABORT();
16075  return SCIP_INVALID; /*lint !e527*/
16076  }
16077 }
16078 
16079 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16080  * was applied
16081  *
16082  * @deprecated Please use SCIPgetVarBdAtIndex()
16083  */
16085  SCIP_VAR* var, /**< problem variable */
16086  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16087  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16088  SCIP_Bool after /**< should the bound change with given index be included? */
16089  )
16090 {
16091  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16092  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16093  else
16094  {
16095  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16096  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16097  }
16098 }
16099 
16100 /** returns whether the binary variable was fixed at the time given by the bound change index
16101  *
16102  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16103  */
16105  SCIP_VAR* var, /**< problem variable */
16106  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16107  SCIP_Bool after /**< should the bound change with given index be included? */
16108  )
16109 {
16110  assert(var != NULL);
16111  assert(SCIPvarIsBinary(var));
16112 
16113  /* check the current bounds first in order to decide at which bound change information we have to look
16114  * (which is expensive because we have to follow the aggregation tree to the active variable)
16115  */
16116  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16117  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16118 }
16119 
16120 /** bound change index representing the initial time before any bound changes took place */
16121 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16123 /** bound change index representing the presolving stage */
16124 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16126 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16128  SCIP_VAR* var /**< problem variable */
16129  )
16130 {
16131  SCIP_BDCHGIDX* lbchgidx;
16132  SCIP_BDCHGIDX* ubchgidx;
16133 
16134  assert(var != NULL);
16135 
16136  var = SCIPvarGetProbvar(var);
16137 
16138  /* check, if variable is original without transformed variable */
16139  if( var == NULL )
16140  return &initbdchgidx;
16141 
16142  /* check, if variable was fixed in presolving */
16143  if( !SCIPvarIsActive(var) )
16144  return &presolvebdchgidx;
16145 
16147 
16148  /* get depths of last bound change information for the lower and upper bound */
16149  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16150  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16151  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16152  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16153 
16154  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16155  return ubchgidx;
16156  else
16157  return lbchgidx;
16158 }
16159 
16160 /** returns the last depth level, at which the bounds of the given variable were tightened;
16161  * returns -2, if the variable's bounds are still the global bounds
16162  * returns -1, if the variable was fixed in presolving
16163  */
16165  SCIP_VAR* var /**< problem variable */
16166  )
16167 {
16168  SCIP_BDCHGIDX* bdchgidx;
16169 
16170  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16171  assert(bdchgidx != NULL);
16172 
16173  return bdchgidx->depth;
16174 }
16175 
16176 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16177  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16178  */
16180  SCIP_VAR* var, /**< problem variable */
16181  SCIP_SET* set, /**< global SCIP settings */
16182  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16183  SCIP_Real bound /**< conflicting bound */
16184  )
16185 {
16186  int i;
16187 
16188  assert(var != NULL);
16189  assert(set != NULL);
16190  assert(var->scip == set->scip);
16191 
16192  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16193  {
16194  /* check if the bound is in conflict with the current local bounds */
16195  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16196  return -1;
16197 
16198  /* check if the bound is in conflict with the global bound */
16199  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16200  return 0;
16201 
16202  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16203  assert(var->nubchginfos > 0);
16204  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16205 
16206  /* search for the first conflicting bound change */
16207  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16208  {
16209  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16211  }
16212  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16213  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16214 
16215  /* return the depth at which the first conflicting bound change took place */
16216  return var->ubchginfos[i].bdchgidx.depth;
16217  }
16218  else
16219  {
16220  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16221 
16222  /* check if the bound is in conflict with the current local bounds */
16223  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16224  return -1;
16225 
16226  /* check if the bound is in conflict with the global bound */
16227  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16228  return 0;
16229 
16230  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16231  assert(var->nlbchginfos > 0);
16232  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16233 
16234  /* search for the first conflicting bound change */
16235  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16236  {
16237  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16239  }
16240  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16241  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16242 
16243  /* return the depth at which the first conflicting bound change took place */
16244  return var->lbchginfos[i].bdchgidx.depth;
16245  }
16246 }
16247 
16248 /** returns whether the first binary variable was fixed earlier than the second one;
16249  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16250  * second one is not fixed
16251  */
16253  SCIP_VAR* var1, /**< first binary variable */
16254  SCIP_VAR* var2 /**< second binary variable */
16255  )
16256 {
16257  SCIP_BDCHGIDX* bdchgidx1;
16258  SCIP_BDCHGIDX* bdchgidx2;
16259 
16260  assert(var1 != NULL);
16261  assert(var2 != NULL);
16262  assert(SCIPvarIsBinary(var1));
16263  assert(SCIPvarIsBinary(var2));
16264 
16265  var1 = SCIPvarGetProbvar(var1);
16266  var2 = SCIPvarGetProbvar(var2);
16267  assert(var1 != NULL);
16268  assert(var2 != NULL);
16269 
16270  /* check, if variables are globally fixed */
16271  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16272  return FALSE;
16273  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16274  return TRUE;
16275 
16278  assert(SCIPvarIsBinary(var1));
16279  assert(SCIPvarIsBinary(var2));
16280  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16281  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16282  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16283  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16284  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16285  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16286 
16287  if( var1->nlbchginfos == 1 )
16288  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16289  else if( var1->nubchginfos == 1 )
16290  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16291  else
16292  bdchgidx1 = NULL;
16293 
16294  if( var2->nlbchginfos == 1 )
16295  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16296  else if( var2->nubchginfos == 1 )
16297  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16298  else
16299  bdchgidx2 = NULL;
16300 
16301  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16302 }
16303 
16304 
16305 
16306 /*
16307  * Hash functions
16308  */
16309 
16310 /** gets the key (i.e. the name) of the given variable */
16311 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16312 { /*lint --e{715}*/
16313  SCIP_VAR* var = (SCIP_VAR*)elem;
16314 
16315  assert(var != NULL);
16316  return var->name;
16317 }
16318 
16319 
16320 
16321 
16322 /*
16323  * simple functions implemented as defines
16324  */
16325 
16326 /* In debug mode, the following methods are implemented as function calls to ensure
16327  * type validity.
16328  * In optimized mode, the methods are implemented as defines to improve performance.
16329  * However, we want to have them in the library anyways, so we have to undef the defines.
16330  */
16331 
16332 #undef SCIPboundchgGetNewbound
16333 #undef SCIPboundchgGetVar
16334 #undef SCIPboundchgGetBoundchgtype
16335 #undef SCIPboundchgGetBoundtype
16336 #undef SCIPboundchgIsRedundant
16337 #undef SCIPdomchgGetNBoundchgs
16338 #undef SCIPdomchgGetBoundchg
16339 #undef SCIPholelistGetLeft
16340 #undef SCIPholelistGetRight
16341 #undef SCIPholelistGetNext
16342 #undef SCIPvarGetName
16343 #undef SCIPvarGetNUses
16344 #undef SCIPvarGetData
16345 #undef SCIPvarSetData
16346 #undef SCIPvarSetDelorigData
16347 #undef SCIPvarSetTransData
16348 #undef SCIPvarSetDeltransData
16349 #undef SCIPvarGetStatus
16350 #undef SCIPvarIsOriginal
16351 #undef SCIPvarIsTransformed
16352 #undef SCIPvarIsNegated
16353 #undef SCIPvarGetType
16354 #undef SCIPvarIsBinary
16355 #undef SCIPvarIsIntegral
16356 #undef SCIPvarIsInitial
16357 #undef SCIPvarIsRemovable
16358 #undef SCIPvarIsDeleted
16359 #undef SCIPvarIsDeletable
16360 #undef SCIPvarMarkDeletable
16361 #undef SCIPvarMarkNotDeletable
16362 #undef SCIPvarIsActive
16363 #undef SCIPvarGetIndex
16364 #undef SCIPvarGetProbindex
16365 #undef SCIPvarGetTransVar
16366 #undef SCIPvarGetCol
16367 #undef SCIPvarIsInLP
16368 #undef SCIPvarGetAggrVar
16369 #undef SCIPvarGetAggrScalar
16370 #undef SCIPvarGetAggrConstant
16371 #undef SCIPvarGetMultaggrNVars
16372 #undef SCIPvarGetMultaggrVars
16373 #undef SCIPvarGetMultaggrScalars
16374 #undef SCIPvarGetMultaggrConstant
16375 #undef SCIPvarGetNegatedVar
16376 #undef SCIPvarGetNegationVar
16377 #undef SCIPvarGetNegationConstant
16378 #undef SCIPvarGetObj
16379 #undef SCIPvarGetLbOriginal
16380 #undef SCIPvarGetUbOriginal
16381 #undef SCIPvarGetHolelistOriginal
16382 #undef SCIPvarGetLbGlobal
16383 #undef SCIPvarGetUbGlobal
16384 #undef SCIPvarGetHolelistGlobal
16385 #undef SCIPvarGetBestBoundGlobal
16386 #undef SCIPvarGetWorstBoundGlobal
16387 #undef SCIPvarGetLbLocal
16388 #undef SCIPvarGetUbLocal
16389 #undef SCIPvarGetHolelistLocal
16390 #undef SCIPvarGetBestBoundLocal
16391 #undef SCIPvarGetWorstBoundLocal
16392 #undef SCIPvarGetBestBoundType
16393 #undef SCIPvarGetWorstBoundType
16394 #undef SCIPvarGetLbLazy
16395 #undef SCIPvarGetUbLazy
16396 #undef SCIPvarGetBranchFactor
16397 #undef SCIPvarGetBranchPriority
16398 #undef SCIPvarGetBranchDirection
16399 #undef SCIPvarGetNVlbs
16400 #undef SCIPvarGetVlbVars
16401 #undef SCIPvarGetVlbCoefs
16402 #undef SCIPvarGetVlbConstants
16403 #undef SCIPvarGetNVubs
16404 #undef SCIPvarGetVubVars
16405 #undef SCIPvarGetVubCoefs
16406 #undef SCIPvarGetVubConstants
16407 #undef SCIPvarGetNImpls
16408 #undef SCIPvarGetImplVars
16409 #undef SCIPvarGetImplTypes
16410 #undef SCIPvarGetImplBounds
16411 #undef SCIPvarGetImplIds
16412 #undef SCIPvarGetNCliques
16413 #undef SCIPvarGetCliques
16414 #undef SCIPvarGetLPSol
16415 #undef SCIPvarGetNLPSol
16416 #undef SCIPvarGetBdchgInfoLb
16417 #undef SCIPvarGetNBdchgInfosLb
16418 #undef SCIPvarGetBdchgInfoUb
16419 #undef SCIPvarGetNBdchgInfosUb
16420 #undef SCIPvarGetValuehistory
16421 #undef SCIPvarGetPseudoSol
16422 #undef SCIPvarCatchEvent
16423 #undef SCIPvarDropEvent
16424 #undef SCIPvarGetVSIDS
16425 #undef SCIPvarGetCliqueComponentIdx
16426 #undef SCIPbdchgidxGetPos
16427 #undef SCIPbdchgidxIsEarlierNonNull
16428 #undef SCIPbdchgidxIsEarlier
16429 #undef SCIPbdchginfoGetOldbound
16430 #undef SCIPbdchginfoGetNewbound
16431 #undef SCIPbdchginfoGetVar
16432 #undef SCIPbdchginfoGetChgtype
16433 #undef SCIPbdchginfoGetBoundtype
16434 #undef SCIPbdchginfoGetDepth
16435 #undef SCIPbdchginfoGetPos
16436 #undef SCIPbdchginfoGetIdx
16437 #undef SCIPbdchginfoGetInferVar
16438 #undef SCIPbdchginfoGetInferCons
16439 #undef SCIPbdchginfoGetInferProp
16440 #undef SCIPbdchginfoGetInferInfo
16441 #undef SCIPbdchginfoGetInferBoundtype
16442 #undef SCIPbdchginfoIsRedundant
16443 #undef SCIPbdchginfoHasInferenceReason
16444 #undef SCIPbdchginfoIsTighter
16445 
16446 
16447 /** returns the new value of the bound in the bound change data */
16449  SCIP_BOUNDCHG* boundchg /**< bound change data */
16450  )
16451 {
16452  assert(boundchg != NULL);
16453 
16454  return boundchg->newbound;
16455 }
16456 
16457 /** returns the variable of the bound change in the bound change data */
16459  SCIP_BOUNDCHG* boundchg /**< bound change data */
16460  )
16461 {
16462  assert(boundchg != NULL);
16463 
16464  return boundchg->var;
16465 }
16466 
16467 /** returns the bound change type of the bound change in the bound change data */
16469  SCIP_BOUNDCHG* boundchg /**< bound change data */
16470  )
16471 {
16472  assert(boundchg != NULL);
16473 
16474  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16475 }
16476 
16477 /** returns the bound type of the bound change in the bound change data */
16479  SCIP_BOUNDCHG* boundchg /**< bound change data */
16480  )
16481 {
16482  assert(boundchg != NULL);
16483 
16484  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16485 }
16486 
16487 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16489  SCIP_BOUNDCHG* boundchg /**< bound change data */
16490  )
16491 {
16492  assert(boundchg != NULL);
16493 
16494  return boundchg->redundant;
16495 }
16496 
16497 /** returns the number of bound changes in the domain change data */
16499  SCIP_DOMCHG* domchg /**< domain change data */
16500  )
16501 {
16502  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16503 }
16504 
16505 /** returns a particular bound change in the domain change data */
16507  SCIP_DOMCHG* domchg, /**< domain change data */
16508  int pos /**< position of the bound change in the domain change data */
16509  )
16510 {
16511  assert(domchg != NULL);
16512  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16513 
16514  return &domchg->domchgbound.boundchgs[pos];
16515 }
16516 
16517 /** returns left bound of open interval in hole */
16519  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16520  )
16521 {
16522  assert(holelist != NULL);
16523 
16524  return holelist->hole.left;
16525 }
16526 
16527 /** returns right bound of open interval in hole */
16529  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16530  )
16531 {
16532  assert(holelist != NULL);
16533 
16534  return holelist->hole.right;
16535 }
16536 
16537 /** returns next hole in list */
16539  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16540  )
16541 {
16542  assert(holelist != NULL);
16543 
16544  return holelist->next;
16545 }
16546 
16547 /** returns the name of the variable
16548  *
16549  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16550  */
16551 const char* SCIPvarGetName(
16552  SCIP_VAR* var /**< problem variable */
16553  )
16554 {
16555  assert(var != NULL);
16556 
16557  return var->name;
16558 }
16559 
16560 /** gets number of times, the variable is currently captured */
16561 int SCIPvarGetNUses(
16562  SCIP_VAR* var /**< problem variable */
16563  )
16564 {
16565  assert(var != NULL);
16566 
16567  return var->nuses;
16568 }
16569 
16570 /** returns the user data of the variable */
16572  SCIP_VAR* var /**< problem variable */
16573  )
16574 {
16575  assert(var != NULL);
16576 
16577  return var->vardata;
16578 }
16579 
16580 /** sets the user data for the variable */
16581 void SCIPvarSetData(
16582  SCIP_VAR* var, /**< problem variable */
16583  SCIP_VARDATA* vardata /**< user variable data */
16584  )
16585 {
16586  assert(var != NULL);
16587 
16588  var->vardata = vardata;
16589 }
16590 
16591 /** sets method to free user data for the original variable */
16593  SCIP_VAR* var, /**< problem variable */
16594  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16595  )
16596 {
16597  assert(var != NULL);
16598  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16599 
16600  var->vardelorig = vardelorig;
16601 }
16602 
16603 /** sets method to transform user data of the variable */
16604 void SCIPvarSetTransData(
16605  SCIP_VAR* var, /**< problem variable */
16606  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16607  )
16608 {
16609  assert(var != NULL);
16610  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16611 
16612  var->vartrans = vartrans;
16613 }
16614 
16615 /** sets method to free transformed user data for the variable */
16617  SCIP_VAR* var, /**< problem variable */
16618  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16619  )
16620 {
16621  assert(var != NULL);
16622 
16623  var->vardeltrans = vardeltrans;
16624 }
16625 
16626 /** sets method to copy this variable into sub-SCIPs */
16627 void SCIPvarSetCopyData(
16628  SCIP_VAR* var, /**< problem variable */
16629  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16630  )
16631 {
16632  assert(var != NULL);
16633 
16634  var->varcopy = varcopy;
16635 }
16636 
16637 /** sets the initial flag of a variable; only possible for original or loose variables */
16639  SCIP_VAR* var, /**< problem variable */
16640  SCIP_Bool initial /**< initial flag */
16641  )
16642 {
16643  assert(var != NULL);
16644 
16646  return SCIP_INVALIDCALL;
16647 
16648  var->initial = initial;
16649 
16650  return SCIP_OKAY;
16651 }
16652 
16653 /** sets the removable flag of a variable; only possible for original or loose variables */
16655  SCIP_VAR* var, /**< problem variable */
16656  SCIP_Bool removable /**< removable flag */
16657  )
16658 {
16659  assert(var != NULL);
16660 
16662  return SCIP_INVALIDCALL;
16663 
16664  var->removable = removable;
16665 
16666  return SCIP_OKAY;
16667 }
16668 
16669 /** gets status of variable */
16671  SCIP_VAR* var /**< problem variable */
16672  )
16673 {
16674  assert(var != NULL);
16675 
16676  return (SCIP_VARSTATUS)(var->varstatus);
16677 }
16678 
16679 /** returns whether the variable belongs to the original problem */
16681  SCIP_VAR* var /**< problem variable */
16682  )
16683 {
16684  assert(var != NULL);
16685  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16686 
16690 }
16691 
16692 /** returns whether the variable belongs to the transformed problem */
16694  SCIP_VAR* var /**< problem variable */
16695  )
16696 {
16697  assert(var != NULL);
16698  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16699 
16703 }
16704 
16705 /** returns whether the variable was created by negation of a different variable */
16707  SCIP_VAR* var /**< problem variable */
16708  )
16709 {
16710  assert(var != NULL);
16711 
16712  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16713 }
16714 
16715 /** gets type of variable */
16717  SCIP_VAR* var /**< problem variable */
16718  )
16719 {
16720  assert(var != NULL);
16721 
16722  return (SCIP_VARTYPE)(var->vartype);
16723 }
16724 
16725 /** returns TRUE if the variable is of binary type; this is the case if:
16726  * (1) variable type is binary
16727  * (2) variable type is integer or implicit integer and
16728  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16729  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16730  */
16732  SCIP_VAR* var /**< problem variable */
16733  )
16734 {
16735  assert(var != NULL);
16736 
16737  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16738  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16739 }
16740 
16741 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16743  SCIP_VAR* var /**< problem variable */
16744  )
16745 {
16746  assert(var != NULL);
16747 
16748  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16749 }
16750 
16751 /** returns whether variable's column should be present in the initial root LP */
16753  SCIP_VAR* var /**< problem variable */
16754  )
16755 {
16756  assert(var != NULL);
16757 
16758  return var->initial;
16759 }
16760 
16761 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16763  SCIP_VAR* var /**< problem variable */
16764  )
16765 {
16766  assert(var != NULL);
16767 
16768  return var->removable;
16769 }
16770 
16771 /** returns whether the variable was deleted from the problem */
16773  SCIP_VAR* var /**< problem variable */
16774  )
16775 {
16776  assert(var != NULL);
16777 
16778  return var->deleted;
16779 }
16780 
16781 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16782  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16783  */
16785  SCIP_VAR* var /**< problem variable */
16786  )
16787 {
16788  assert(var != NULL);
16789  assert(var->probindex == -1);
16790 
16791  var->deletable = TRUE;
16792 }
16793 
16794 /** marks the variable to be not deletable from the problem */
16797  )
16798 {
16799  assert(var != NULL);
16800 
16801  var->deletable = FALSE;
16802 }
16803 
16804 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16805  *
16806  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16807  */
16809  SCIP_VAR* var /**< problem variable */
16810  )
16811 {
16812  assert(var != NULL);
16813 
16814  var->delglobalstructs = TRUE;
16815 }
16816 
16817 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16819  SCIP_VAR* var /**< problem variable */
16820  )
16821 {
16822  assert(var != NULL);
16823 
16824  return var->delglobalstructs;
16825 }
16826 
16827 /** returns whether variable is allowed to be deleted completely from the problem */
16830  )
16831 {
16832  assert(var != NULL);
16833 
16834  return var->deletable;
16835 }
16836 
16837 /** returns whether variable is an active (neither fixed nor aggregated) variable */
16839  SCIP_VAR* var /**< problem variable */
16840  )
16841 {
16842  assert(var != NULL);
16843 
16844  return (var->probindex >= 0);
16845 }
16846 
16847 /** gets unique index of variable */
16848 int SCIPvarGetIndex(
16849  SCIP_VAR* var /**< problem variable */
16850  )
16851 {
16852  assert(var != NULL);
16853 
16854  return var->index;
16855 }
16856 
16857 /** gets position of variable in problem, or -1 if variable is not active */
16859  SCIP_VAR* var /**< problem variable */
16860  )
16861 {
16862  assert(var != NULL);
16863 
16864  return var->probindex;
16865 }
16866 
16867 /** gets transformed variable of ORIGINAL variable */
16869  SCIP_VAR* var /**< problem variable */
16870  )
16871 {
16872  assert(var != NULL);
16873  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16874 
16875  return var->data.original.transvar;
16876 }
16877 
16878 /** gets column of COLUMN variable */
16880  SCIP_VAR* var /**< problem variable */
16881  )
16882 {
16883  assert(var != NULL);
16884  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16885 
16886  return var->data.col;
16887 }
16888 
16889 /** returns whether the variable is a COLUMN variable that is member of the current LP */
16891  SCIP_VAR* var /**< problem variable */
16892  )
16893 {
16894  assert(var != NULL);
16895 
16896  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
16897 }
16898 
16899 /** gets aggregation variable y of an aggregated variable x = a*y + c */
16901  SCIP_VAR* var /**< problem variable */
16902  )
16903 {
16904  assert(var != NULL);
16906 
16907  return var->data.aggregate.var;
16908 }
16909 
16910 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
16912  SCIP_VAR* var /**< problem variable */
16913  )
16914 {
16915  assert(var != NULL);
16917 
16918  return var->data.aggregate.scalar;
16919 }
16920 
16921 /** gets aggregation constant c of an aggregated variable x = a*y + c */
16923  SCIP_VAR* var /**< problem variable */
16924  )
16925 {
16926  assert(var != NULL);
16928 
16929  return var->data.aggregate.constant;
16930 }
16931 
16932 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16934  SCIP_VAR* var /**< problem variable */
16935  )
16936 {
16937  assert(var != NULL);
16938  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16939  assert(!var->donotmultaggr);
16940 
16941  return var->data.multaggr.nvars;
16942 }
16943 
16944 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16946  SCIP_VAR* var /**< problem variable */
16947  )
16948 {
16949  assert(var != NULL);
16950  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16951  assert(!var->donotmultaggr);
16952 
16953  return var->data.multaggr.vars;
16954 }
16955 
16956 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16958  SCIP_VAR* var /**< problem variable */
16959  )
16960 {
16961  assert(var != NULL);
16962  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16963  assert(!var->donotmultaggr);
16964 
16965  return var->data.multaggr.scalars;
16966 }
16967 
16968 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
16970  SCIP_VAR* var /**< problem variable */
16971  )
16972 {
16973  assert(var != NULL);
16974  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
16975  assert(!var->donotmultaggr);
16976 
16977  return var->data.multaggr.constant;
16978 }
16979 
16980 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
16982  SCIP_VAR* var /**< negated problem variable */
16983  )
16984 {
16985  assert(var != NULL);
16986 
16987  return var->negatedvar;
16988 }
16989 
16990 /** gets the negation variable x of a negated variable x' = offset - x */
16992  SCIP_VAR* var /**< negated problem variable */
16993  )
16994 {
16995  assert(var != NULL);
16996  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16997 
16998  return var->negatedvar;
16999 }
17000 
17001 /** gets the negation offset of a negated variable x' = offset - x */
17003  SCIP_VAR* var /**< negated problem variable */
17004  )
17005 {
17006  assert(var != NULL);
17007  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17008 
17009  return var->data.negate.constant;
17010 }
17011 
17012 /** gets objective function value of variable */
17014  SCIP_VAR* var /**< problem variable */
17015  )
17016 {
17017  assert(var != NULL);
17018 
17019  return var->obj;
17020 }
17021 
17022 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17024  SCIP_VAR* var /**< problem variable */
17025  )
17026 {
17027  assert(var != NULL);
17028 
17029  return var->unchangedobj;
17030 }
17031 
17032 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17033  * e.g. obj(x) = 1 this method returns for ~x the value -1
17034  */
17036  SCIP_VAR* var, /**< problem variable */
17037  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17038  )
17039 {
17040  SCIP_VAR* probvar = var;
17041  SCIP_Real mult = 1.0;
17042 
17043  assert(probvar != NULL);
17044  assert(aggrobj != NULL);
17045 
17046  while( probvar != NULL )
17047  {
17048  switch( SCIPvarGetStatus(probvar) )
17049  {
17051  case SCIP_VARSTATUS_LOOSE:
17052  case SCIP_VARSTATUS_COLUMN:
17053  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17054  return SCIP_OKAY;
17055 
17056  case SCIP_VARSTATUS_FIXED:
17057  assert(SCIPvarGetObj(probvar) == 0.0);
17058  (*aggrobj) = 0.0;
17059  return SCIP_OKAY;
17060 
17062  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17063  if ( probvar->data.multaggr.nvars == 1 )
17064  {
17065  assert( probvar->data.multaggr.vars != NULL );
17066  assert( probvar->data.multaggr.scalars != NULL );
17067  assert( probvar->data.multaggr.vars[0] != NULL );
17068  mult *= probvar->data.multaggr.scalars[0];
17069  probvar = probvar->data.multaggr.vars[0];
17070  break;
17071  }
17072  else
17073  {
17074  SCIP_Real tmpobj;
17075  int v;
17076 
17077  (*aggrobj) = 0.0;
17078 
17079  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17080  {
17081  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17082  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17083  }
17084  return SCIP_OKAY;
17085  }
17086 
17087  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17088  assert(probvar->data.aggregate.var != NULL);
17089  mult *= probvar->data.aggregate.scalar;
17090  probvar = probvar->data.aggregate.var;
17091  break;
17092 
17093  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17094  assert(probvar->negatedvar != NULL);
17095  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17096  assert(probvar->negatedvar->negatedvar == probvar);
17097  mult *= -1.0;
17098  probvar = probvar->negatedvar;
17099  break;
17100 
17101  default:
17102  SCIPABORT();
17103  return SCIP_INVALIDDATA; /*lint !e527*/
17104  }
17105  }
17106 
17107  return SCIP_INVALIDDATA;
17108 }
17109 
17110 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17112  SCIP_VAR* var /**< original problem variable */
17113  )
17114 {
17115  assert(var != NULL);
17116  assert(SCIPvarIsOriginal(var));
17117 
17119  return var->data.original.origdom.lb;
17120  else
17121  {
17122  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17123  assert(var->negatedvar != NULL);
17125 
17126  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17127  }
17128 }
17129 
17130 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17132  SCIP_VAR* var /**< original problem variable */
17133  )
17134 {
17135  assert(var != NULL);
17136  assert(SCIPvarIsOriginal(var));
17137 
17139  return var->data.original.origdom.ub;
17140  else
17141  {
17142  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17143  assert(var->negatedvar != NULL);
17145 
17146  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17147  }
17148 }
17149 
17150 /** gets the original hole list of an original variable */
17152  SCIP_VAR* var /**< problem variable */
17153  )
17154 {
17155  assert(var != NULL);
17156  assert(SCIPvarIsOriginal(var));
17157 
17159  return var->data.original.origdom.holelist;
17160 
17161  return NULL;
17162 }
17163 
17164 /** gets global lower bound of variable */
17166  SCIP_VAR* var /**< problem variable */
17167  )
17168 {
17169  assert(var != NULL);
17170 
17171  return var->glbdom.lb;
17172 }
17173 
17174 /** gets global upper bound of variable */
17176  SCIP_VAR* var /**< problem variable */
17177  )
17178 {
17179  assert(var != NULL);
17180 
17181  return var->glbdom.ub;
17182 }
17183 
17184 /** gets the global hole list of an active variable */
17186  SCIP_VAR* var /**< problem variable */
17187  )
17188 {
17189  assert(var != NULL);
17190 
17191  return var->glbdom.holelist;
17192 }
17193 
17194 /** gets best global bound of variable with respect to the objective function */
17196  SCIP_VAR* var /**< problem variable */
17197  )
17198 {
17199  assert(var != NULL);
17200 
17201  if( var->obj >= 0.0 )
17202  return var->glbdom.lb;
17203  else
17204  return var->glbdom.ub;
17205 }
17206 
17207 /** gets worst global bound of variable with respect to the objective function */
17209  SCIP_VAR* var /**< problem variable */
17210  )
17211 {
17212  assert(var != NULL);
17213 
17214  if( var->obj >= 0.0 )
17215  return var->glbdom.ub;
17216  else
17217  return var->glbdom.lb;
17218 }
17219 
17220 /** gets current lower bound of variable */
17222  SCIP_VAR* var /**< problem variable */
17223  )
17224 {
17225  assert(var != NULL);
17226 
17227  return var->locdom.lb;
17228 }
17229 
17230 /** gets current upper bound of variable */
17232  SCIP_VAR* var /**< problem variable */
17233  )
17234 {
17235  assert(var != NULL);
17236 
17237  return var->locdom.ub;
17238 }
17239 
17240 /** gets the current hole list of an active variable */
17242  SCIP_VAR* var /**< problem variable */
17243  )
17244 {
17245  assert(var != NULL);
17246 
17247  return var->locdom.holelist;
17248 }
17249 
17250 /** gets best local bound of variable with respect to the objective function */
17252  SCIP_VAR* var /**< problem variable */
17253  )
17254 {
17255  assert(var != NULL);
17256 
17257  if( var->obj >= 0.0 )
17258  return var->locdom.lb;
17259  else
17260  return var->locdom.ub;
17261 }
17262 
17263 /** gets worst local bound of variable with respect to the objective function */
17265  SCIP_VAR* var /**< problem variable */
17266  )
17267 {
17268  assert(var != NULL);
17269 
17270  if( var->obj >= 0.0 )
17271  return var->locdom.ub;
17272  else
17273  return var->locdom.lb;
17274 }
17275 
17276 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17278  SCIP_VAR* var /**< problem variable */
17279  )
17280 {
17281  assert(var != NULL);
17282 
17283  if( var->obj >= 0.0 )
17284  return SCIP_BOUNDTYPE_LOWER;
17285  else
17286  return SCIP_BOUNDTYPE_UPPER;
17287 }
17288 
17289 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17291  SCIP_VAR* var /**< problem variable */
17292  )
17293 {
17294  assert(var != NULL);
17295 
17296  if( var->obj >= 0.0 )
17297  return SCIP_BOUNDTYPE_UPPER;
17298  else
17299  return SCIP_BOUNDTYPE_LOWER;
17300 }
17301 
17302 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17304  SCIP_VAR* var /**< problem variable */
17305  )
17306 {
17307  assert(var != NULL);
17308 
17309  return var->lazylb;
17310 }
17311 
17312 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17314  SCIP_VAR* var /**< problem variable */
17315  )
17316 {
17317  assert(var != NULL);
17318 
17319  return var->lazyub;
17320 }
17321 
17322 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17323  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17324  */
17326  SCIP_VAR* var /**< problem variable */
17327  )
17328 {
17329  assert(var != NULL);
17330 
17331  return var->branchfactor;
17332 }
17333 
17334 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17335  * with lower priority
17336  */
17338  SCIP_VAR* var /**< problem variable */
17339  )
17340 {
17341  assert(var != NULL);
17342 
17343  return var->branchpriority;
17344 }
17345 
17346 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17348  SCIP_VAR* var /**< problem variable */
17349  )
17350 {
17351  assert(var != NULL);
17352 
17353  return (SCIP_BRANCHDIR)var->branchdirection;
17354 }
17355 
17356 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17357 int SCIPvarGetNVlbs(
17358  SCIP_VAR* var /**< problem variable */
17359  )
17360 {
17361  assert(var != NULL);
17362 
17363  return SCIPvboundsGetNVbds(var->vlbs);
17364 }
17365 
17366 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17367  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17368  */
17370  SCIP_VAR* var /**< problem variable */
17371  )
17372 {
17373  assert(var != NULL);
17374 
17375  return SCIPvboundsGetVars(var->vlbs);
17376 }
17377 
17378 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17380  SCIP_VAR* var /**< problem variable */
17381  )
17382 {
17383  assert(var != NULL);
17384 
17385  return SCIPvboundsGetCoefs(var->vlbs);
17386 }
17387 
17388 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17390  SCIP_VAR* var /**< problem variable */
17391  )
17392 {
17393  assert(var != NULL);
17394 
17395  return SCIPvboundsGetConstants(var->vlbs);
17396 }
17397 
17398 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17399 int SCIPvarGetNVubs(
17400  SCIP_VAR* var /**< problem variable */
17401  )
17402 {
17403  assert(var != NULL);
17404 
17405  return SCIPvboundsGetNVbds(var->vubs);
17406 }
17407 
17408 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17409  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17410  */
17412  SCIP_VAR* var /**< problem variable */
17413  )
17414 {
17415  assert(var != NULL);
17416 
17417  return SCIPvboundsGetVars(var->vubs);
17418 }
17419 
17420 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17422  SCIP_VAR* var /**< problem variable */
17423  )
17424 {
17425  assert(var != NULL);
17426 
17427  return SCIPvboundsGetCoefs(var->vubs);
17428 }
17429 
17430 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17432  SCIP_VAR* var /**< problem variable */
17433  )
17434 {
17435  assert(var != NULL);
17436 
17437  return SCIPvboundsGetConstants(var->vubs);
17438 }
17439 
17440 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17441  * there are no implications for nonbinary variable x
17442  */
17443 int SCIPvarGetNImpls(
17444  SCIP_VAR* var, /**< active problem variable */
17445  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17446  )
17447 {
17448  assert(var != NULL);
17449  assert(SCIPvarIsActive(var));
17450 
17451  return SCIPimplicsGetNImpls(var->implics, varfixing);
17452 }
17453 
17454 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17455  * problem variable x, there are no implications for nonbinary variable x;
17456  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17457  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17458  * (see SCIPvarGetIndex())
17459  */
17461  SCIP_VAR* var, /**< active problem variable */
17462  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17463  )
17464 {
17465  assert(var != NULL);
17466  assert(SCIPvarIsActive(var));
17467 
17468  return SCIPimplicsGetVars(var->implics, varfixing);
17469 }
17470 
17471 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17472  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17473  * there are no implications for nonbinary variable x
17474  */
17476  SCIP_VAR* var, /**< active problem variable */
17477  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17478  )
17479 {
17480  assert(var != NULL);
17481  assert(SCIPvarIsActive(var));
17482 
17483  return SCIPimplicsGetTypes(var->implics, varfixing);
17484 }
17485 
17486 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17487  * variable x, there are no implications for nonbinary variable x
17488  */
17490  SCIP_VAR* var, /**< active problem variable */
17491  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17492  )
17493 {
17494  assert(var != NULL);
17495  assert(SCIPvarIsActive(var));
17496 
17497  return SCIPimplicsGetBounds(var->implics, varfixing);
17498 }
17499 
17500 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17501  * there are no implications for nonbinary variable x.
17502  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17503  * its id is negative, otherwise it is nonnegative.
17504  */
17505 int* SCIPvarGetImplIds(
17506  SCIP_VAR* var, /**< active problem variable */
17507  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17508  )
17509 {
17510  assert(var != NULL);
17511  assert(SCIPvarIsActive(var));
17512 
17513  return SCIPimplicsGetIds(var->implics, varfixing);
17514 }
17515 
17516 /** gets number of cliques, the active variable is contained in */
17517 int SCIPvarGetNCliques(
17518  SCIP_VAR* var, /**< active problem variable */
17519  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17520  )
17521 {
17522  assert(var != NULL);
17523 
17524  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17525 }
17526 
17527 /** gets array of cliques, the active variable is contained in */
17529  SCIP_VAR* var, /**< active problem variable */
17530  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17531  )
17532 {
17533  assert(var != NULL);
17534 
17535  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17536 }
17537 
17538 /** gets primal LP solution value of variable */
17540  SCIP_VAR* var /**< problem variable */
17541  )
17542 {
17543  assert(var != NULL);
17544 
17546  return SCIPcolGetPrimsol(var->data.col);
17547  else
17548  return SCIPvarGetLPSol_rec(var);
17549 }
17550 
17551 /** gets primal NLP solution value of variable */
17553  SCIP_VAR* var /**< problem variable */
17554  )
17555 {
17556  assert(var != NULL);
17557 
17559  return var->nlpsol;
17560  else
17561  return SCIPvarGetNLPSol_rec(var);
17562 }
17563 
17564 /** return lower bound change info at requested position */
17566  SCIP_VAR* var, /**< problem variable */
17567  int pos /**< requested position */
17568  )
17569 {
17570  assert(pos >= 0);
17571  assert(pos < var->nlbchginfos);
17572 
17573  return &var->lbchginfos[pos];
17574 }
17575 
17576 /** gets the number of lower bound change info array */
17578  SCIP_VAR* var /**< problem variable */
17579  )
17580 {
17581  return var->nlbchginfos;
17582 }
17583 
17584 /** return upper bound change info at requested position */
17586  SCIP_VAR* var, /**< problem variable */
17587  int pos /**< requested position */
17588  )
17589 {
17590  assert(pos >= 0);
17591  assert(pos < var->nubchginfos);
17592 
17593  return &var->ubchginfos[pos];
17594 }
17595 
17596 /** gets the number upper bound change info array */
17598  SCIP_VAR* var /**< problem variable */
17599  )
17600 {
17601  assert(var != NULL);
17602 
17603  return var->nubchginfos;
17604 }
17605 
17606 /** returns the value based history for the variable */
17608  SCIP_VAR* var /**< problem variable */
17609  )
17610 {
17611  assert(var != NULL);
17612 
17613  return var->valuehistory;
17614 }
17615 
17616 /** gets pseudo solution value of variable */
17618  SCIP_VAR* var /**< problem variable */
17619  )
17620 {
17621  assert(var != NULL);
17622 
17624  return SCIPvarGetBestBoundLocal(var);
17625  else
17626  return SCIPvarGetPseudoSol_rec(var);
17627 }
17628 
17629 /** returns the variable's VSIDS score */
17631  SCIP_VAR* var, /**< problem variable */
17632  SCIP_STAT* stat, /**< problem statistics */
17633  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17634  )
17635 {
17636  assert(var != NULL);
17637 
17639  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17640  else
17641  return SCIPvarGetVSIDS_rec(var, stat, dir);
17642 }
17643 
17644 /** returns the index of the connected component of the clique graph that the variable belongs to, or -1 if not computed */
17646  SCIP_VAR* var /**< problem variable */
17647  )
17648 {
17649  assert(var != NULL);
17650  return var->clqcomponentidx;
17651 }
17652 
17653 /** sets the index of the connected component of the clique graph that the variable belongs to, or -1 if not computed */
17655  SCIP_VAR* var, /**< problem variable */
17656  int idx /**< clique component index of this variable */
17657  )
17658 {
17659  assert(var != NULL);
17660  var->clqcomponentidx = idx;
17661 }
17662 
17663 
17664 /** includes event handler with given data in variable's event filter */
17666  SCIP_VAR* var, /**< problem variable */
17667  BMS_BLKMEM* blkmem, /**< block memory */
17668  SCIP_SET* set, /**< global SCIP settings */
17669  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17670  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17671  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17672  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17673  )
17674 {
17675  assert(var != NULL);
17676  assert(set != NULL);
17677  assert(var->scip == set->scip);
17678  assert(var->eventfilter != NULL);
17679  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17680  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17681  assert(SCIPvarIsTransformed(var));
17682 
17683  SCIPsetDebugMsg(set, "catch event of type 0x%"SCIP_EVENTTYPE_FORMAT" of variable <%s> with handler %p and data %p\n",
17684  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17685 
17686  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17687 
17688  return SCIP_OKAY;
17689 }
17690 
17691 /** deletes event handler with given data from variable's event filter */
17693  SCIP_VAR* var, /**< problem variable */
17694  BMS_BLKMEM* blkmem, /**< block memory */
17695  SCIP_SET* set, /**< global SCIP settings */
17696  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17697  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17698  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17699  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17700  )
17701 {
17702  assert(var != NULL);
17703  assert(set != NULL);
17704  assert(var->scip == set->scip);
17705  assert(var->eventfilter != NULL);
17706  assert(SCIPvarIsTransformed(var));
17707 
17708  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17709  (void*)eventdata);
17710 
17711  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17712 
17713  return SCIP_OKAY;
17714 }
17715 
17716 /** returns the position of the bound change index */
17717 int SCIPbdchgidxGetPos(
17718  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17719  )
17720 {
17721  assert(bdchgidx != NULL);
17722 
17723  return bdchgidx->pos;
17724 }
17725 
17726 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17728  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17729  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17730  )
17731 {
17732  assert(bdchgidx1 != NULL);
17733  assert(bdchgidx1->depth >= -2);
17734  assert(bdchgidx1->pos >= 0);
17735  assert(bdchgidx2 != NULL);
17736  assert(bdchgidx2->depth >= -2);
17737  assert(bdchgidx2->pos >= 0);
17738 
17739  return (bdchgidx1->depth < bdchgidx2->depth)
17740  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17741 }
17742 
17743 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17744  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17745  * last bound change was applied to the current node
17746  */
17748  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17749  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17750  )
17751 {
17752  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17753  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17754  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17755  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17756 
17757  if( bdchgidx1 == NULL )
17758  return FALSE;
17759  else if( bdchgidx2 == NULL )
17760  return TRUE;
17761  else
17762  return (bdchgidx1->depth < bdchgidx2->depth)
17763  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17764 }
17765 
17766 /** returns old bound that was overwritten for given bound change information */
17768  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17769  )
17770 {
17771  assert(bdchginfo != NULL);
17772 
17773  return bdchginfo->oldbound;
17774 }
17775 
17776 /** returns new bound installed for given bound change information */
17778  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17779  )
17780 {
17781  assert(bdchginfo != NULL);
17782 
17783  return bdchginfo->newbound;
17784 }
17785 
17786 /** returns variable that belongs to the given bound change information */
17788  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17789  )
17790 {
17791  assert(bdchginfo != NULL);
17792 
17793  return bdchginfo->var;
17794 }
17795 
17796 /** returns whether the bound change information belongs to a branching decision or a deduction */
17798  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17799  )
17800 {
17801  assert(bdchginfo != NULL);
17802 
17803  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17804 }
17805 
17806 /** returns whether the bound change information belongs to a lower or upper bound change */
17808  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17809  )
17810 {
17811  assert(bdchginfo != NULL);
17812 
17813  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17814 }
17815 
17816 /** returns depth level of given bound change information */
17818  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17819  )
17820 {
17821  assert(bdchginfo != NULL);
17822 
17823  return bdchginfo->bdchgidx.depth;
17824 }
17825 
17826 /** returns bound change position in its depth level of given bound change information */
17828  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17829  )
17830 {
17831  assert(bdchginfo != NULL);
17832 
17833  return bdchginfo->bdchgidx.pos;
17834 }
17835 
17836 /** returns bound change index of given bound change information */
17838  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17839  )
17840 {
17841  assert(bdchginfo != NULL);
17842 
17843  return &bdchginfo->bdchgidx;
17844 }
17845 
17846 /** returns inference variable of given bound change information */
17848  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17849  )
17850 {
17851  assert(bdchginfo != NULL);
17854 
17855  return bdchginfo->inferencedata.var;
17856 }
17857 
17858 /** returns inference constraint of given bound change information */
17860  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17861  )
17862 {
17863  assert(bdchginfo != NULL);
17865  assert(bdchginfo->inferencedata.reason.cons != NULL);
17866 
17867  return bdchginfo->inferencedata.reason.cons;
17868 }
17869 
17870 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
17872  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17873  )
17874 {
17875  assert(bdchginfo != NULL);
17877 
17878  return bdchginfo->inferencedata.reason.prop;
17879 }
17880 
17881 /** returns inference user information of given bound change information */
17883  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17884  )
17885 {
17886  assert(bdchginfo != NULL);
17889 
17890  return bdchginfo->inferencedata.info;
17891 }
17892 
17893 /** returns inference bound of inference variable of given bound change information */
17895  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17896  )
17897 {
17898  assert(bdchginfo != NULL);
17901 
17902  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
17903 }
17904 
17905 /** returns the relaxed bound change type */
17907  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
17908  )
17909 {
17910  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
17911 }
17912 
17913 
17914 /** returns whether the bound change information belongs to a redundant bound change */
17916  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17917  )
17918 {
17919  assert(bdchginfo != NULL);
17920  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
17921 
17922  return bdchginfo->redundant;
17923 }
17924 
17925 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
17927  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17928  )
17929 {
17930  assert(bdchginfo != NULL);
17931 
17934  && bdchginfo->inferencedata.reason.prop != NULL);
17935 }
17936 
17937 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
17938  * has a tighter new bound as the second bound change
17939  */
17941  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
17942  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
17943  )
17944 {
17945  assert(bdchginfo1 != NULL);
17946  assert(bdchginfo2 != NULL);
17947  assert(bdchginfo1->var == bdchginfo2->var);
17948  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
17949 
17950  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
17951  ? bdchginfo1->newbound > bdchginfo2->newbound
17952  : bdchginfo1->newbound < bdchginfo2->newbound);
17953 }
enum SCIP_Result SCIP_RESULT
Definition: type_result.h:52
SCIP_Real SCIPhistoryGetAvgConflictlength(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:555
SCIP_HOLELIST * holelist
Definition: struct_var.h:162
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1693
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17907
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1663
static SCIP_Real adjustedUb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real ub)
Definition: var.c:1511
SCIP_Real SCIPvarGetAvgConflictlengthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14706
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17265
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5522
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17380
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:422
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13424
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:924
SCIP_BOUNDTYPE SCIPvarGetWorstBoundType(SCIP_VAR *var)
Definition: var.c:17291
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:8911
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:14833
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10785
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:86
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:568
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3305
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5580
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6030
internal methods for storing primal CIP solutions
void SCIPhistoryIncVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:487
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:14353
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8793
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:9902
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16085
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17872
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16796
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12584
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13308
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16799
int nubchginfos
Definition: struct_var.h:264
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:5876
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17566
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:16958
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:41382
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:111
void SCIPhistoryIncCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:600
SCIP_Real SCIPvarGetAvgCutoffsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15606
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:228
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5426
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17326
unsigned int inferboundtype
Definition: struct_var.h:92
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17768
char * name
Definition: struct_var.h:228
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:962
unsigned int boundchgtype
Definition: struct_var.h:113
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17348
union SCIP_BoundChg::@11 data
SCIP_RETCODE SCIPcliqueAddVar(SCIP_CLIQUE *clique, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Bool value, SCIP_Bool *doubleentry, SCIP_Bool *oppositeentry)
Definition: implics.c:1131
SCIP_HOLE hole
Definition: struct_var.h:50
SCIP_Real bestrootsol
Definition: struct_var.h:206
char * name
Definition: struct_lp.h:215
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17314
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5709
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:6370
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5920
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17358
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17788
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1836
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17209
#define SCIP_DECL_VARTRANS(x)
Definition: type_var.h:129
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:6720
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5492
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:2036
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13918
methods for implications, variable bounds, and cliques
SCIP_RETCODE SCIPvarAggregate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_CLIQUETABLE *cliquetable, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *aggregated)
Definition: var.c:4422
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16165
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:2112
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17166
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15089
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11616
SCIP_RETCODE SCIPdomchgAddHolechg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST **ptr, SCIP_HOLELIST *newlist, SCIP_HOLELIST *oldlist)
Definition: var.c:1442
SCIP_Bool SCIPvarIsPscostRelerrorReliable(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real threshold, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14085
#define SCIP_MAXSTRLEN
Definition: def.h:215
SCIP_DOM origdom
Definition: struct_var.h:168
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16070
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16753
SCIP_RETCODE SCIPeventCreateImplAdded(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:766
SCIP_VAR ** SCIPimplicsGetVars(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3256
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6102
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:124
void SCIPhistoryIncInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real weight)
Definition: history.c:584
SCIP_Bool SCIPsetIsPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5645
SCIP_Real lastbranchvalue
Definition: struct_stat.h:128
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1032
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:16946
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:259
#define MAXABSVBCOEF
Definition: var.c:66
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1845
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12718
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15660
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:1851
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17222
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7004
SCIP_Real constant
Definition: struct_var.h:183
SCIP_RETCODE SCIPvarAddLocks(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int addnlocksdown, int addnlocksup)
Definition: var.c:3047
SCIP_CLIQUE ** SCIPvarGetCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17529
SCIP_RETCODE SCIPprobVarChangedStatus(SCIP_PROB *prob, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BRANCHCAND *branchcand, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var)
Definition: prob.c:1171
SCIP_Real bestrootredcost
Definition: struct_var.h:207
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8095
SCIP_HISTORY * historycrun
Definition: struct_var.h:244
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:165
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17608
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3357
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7423
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1419
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16605
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6161
SCIP_Longint closestvblpcount
Definition: struct_var.h:246
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:8403
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:2404
SCIP_Bool SCIPvarIsBinary(SCIP_VAR *var)
Definition: var.c:16732
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:6297
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3223
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5384
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:153
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3557
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12561
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2243
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:242
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17748
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16105
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17252
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12654
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:832
SCIP_RETCODE SCIPvarMarkDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5715
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14439
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12238
static SCIP_RETCODE holelistDuplicate(SCIP_HOLELIST **target, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HOLELIST *source)
Definition: var.c:124
SCIP_BOUNDTYPE SCIPboundchgGetBoundtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16479
unsigned int nboundchgs
Definition: struct_var.h:122
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:17666
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:3138
SCIP_HOLELIST * newlist
Definition: struct_var.h:58
SCIP_Real right
Definition: struct_var.h:44
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:314
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5635
SCIP_RETCODE SCIPhistoryCreate(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:40
static SCIP_RETCODE varUpdateAggregationBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *aggvar, SCIP_Real scalar, SCIP_Real constant, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:4232
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16539
#define FALSE
Definition: def.h:64
int lppos
Definition: struct_lp.h:161
#define EPSEQ(x, y, eps)
Definition: def.h:160
#define EPSISINT(x, eps)
Definition: def.h:172
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:16789
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6063
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17578
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:476
struct SCIP_VarData SCIP_VARDATA
Definition: type_var.h:98
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:1271
SCIP_Real SCIPcolGetUb(SCIP_COL *col)
Definition: lp.c:16012
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:747
SCIP_RETCODE SCIPvarTransform(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_OBJSENSE objsense, SCIP_VAR **transvar)
Definition: var.c:3290
void SCIPhistoryReset(SCIP_HISTORY *history)
Definition: history.c:67
SCIP_Real SCIPcolGetObj(SCIP_COL *col)
Definition: lp.c:15992
static SCIP_RETCODE varEventVarUnlocked(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:3026
SCIP_Real constant
Definition: struct_var.h:193
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:9340
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5634
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:281
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14325
#define TRUE
Definition: def.h:63
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10456
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5616
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14662
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:110
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_HOLELIST * oldlist
Definition: struct_var.h:59
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17003
#define MAXIMPLSCLOSURE
Definition: var.c:63
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17400
SCIP_RETCODE SCIPeventCreateUbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:652
int SCIPbdchginfoGetInferInfo(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17883
int nlbchginfos
Definition: struct_var.h:262
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16125
static void printHolelist(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_HOLELIST *holelist, const char *name)
Definition: var.c:2851
enum SCIP_Varstatus SCIP_VARSTATUS
Definition: type_var.h:48
#define SCIPsetAllocBufferArray(set, ptr, num)
Definition: set.h:1834
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:1993
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16859
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:10257
#define SCIP_DECL_VARCOPY(x)
Definition: type_var.h:172
SCIP_RETCODE SCIPvarChgLbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7778
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5650
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5096
#define SCIP_EVENTTYPE_GLBCHANGED
Definition: type_event.h:61
SCIP_RETCODE SCIPvarChgBdLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype)
Definition: var.c:7752
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:16912
void SCIPvarInitSolve(SCIP_VAR *var)
Definition: var.c:2810
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:6863
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15273
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16785
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:1855
SCIP_RETCODE SCIPimplicsDel(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:833
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15361
SCIP_Real SCIPhistoryGetVSIDS(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:513
#define SCIPdebugMessage
Definition: pub_message.h:77
SCIP_RETCODE SCIPvarAddClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique, SCIP_Bool *infeasible, int *nbdchgs)
Definition: var.c:10580
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17370
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1529
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11313
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17718
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3366
int index
Definition: struct_var.h:249
SCIP_Real constant
Definition: struct_var.h:176
unsigned int domchgtype
Definition: struct_var.h:141
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5656
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1462
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16829
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16180
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13679
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1841
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15046
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16763
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6052
static SCIP_RETCODE domchgEnsureBoundchgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1173
#define SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant)
Definition: debug.h:258
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11126
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:668
SCIP_HOLECHG * holechgs
Definition: struct_var.h:133
SCIP_Real obj
Definition: struct_var.h:202
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:16992
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:5348
SCIP_Real relaxsol
Definition: struct_var.h:209
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:1532
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:892
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5720
int conflictlbcount
Definition: struct_var.h:265
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13297
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:242
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16128
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17518
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12375
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:423
SCIP_VAR ** vars
Definition: struct_var.h:185
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:190
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:199
int branchpriority
Definition: struct_var.h:260
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15516
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17506
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17152
SCIP_RETCODE SCIPeventCreateObjChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldobj, SCIP_Real newobj)
Definition: event.c:557
internal methods for collecting primal CIP solutions and primal informations
SCIP_Real SCIPsolGetVal(SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *var)
Definition: sol.c:1286
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:2262
SCIP_RETCODE SCIPvboundsAdd(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_BOUNDTYPE vboundtype, SCIP_VAR *var, SCIP_Real coef, SCIP_Real constant, SCIP_Bool *added)
Definition: implics.c:199
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11306
SCIP_VAR * var
Definition: struct_var.h:177
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12308
int nrootboundchgs
Definition: struct_stat.h:197
#define SCIP_DECL_VARDELTRANS(x)
Definition: type_var.h:142
SCIP_Bool SCIPsetIsGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5616
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:7081
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:160
internal methods for propagators
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:16982
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10724
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:2997
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15228
void SCIPhistoryScaleVSIDS(SCIP_HISTORY *history, SCIP_Real scalar)
Definition: history.c:501
enum SCIP_BranchDir SCIP_BRANCHDIR
Definition: type_history.h:39
SCIP_Bool SCIPrealToRational(SCIP_Real val, SCIP_Real mindelta, SCIP_Real maxdelta, SCIP_Longint maxdnom, SCIP_Longint *nominator, SCIP_Longint *denominator)
Definition: misc.c:8077
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12447
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17598
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1421
SCIP_Real conflictrelaxedub
Definition: struct_var.h:215
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7143
void SCIPvarSetCliqueComponentIdx(SCIP_VAR *var, int idx)
Definition: var.c:17655
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:17941
unsigned int inferboundtype
Definition: struct_var.h:115
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:514
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:7501
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17176
union SCIP_Var::@12 data
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5562
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11524
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12192
SCIP_RETCODE SCIPvaluehistoryFind(SCIP_VALUEHISTORY *valuehistory, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real value, SCIP_HISTORY **history)
Definition: history.c:269
SCIP_RETCODE SCIPvarChgType(SCIP_VAR *var, SCIP_VARTYPE vartype)
Definition: var.c:5750
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13118
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4217
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10806
SCIP_Real SCIPhistoryGetPseudocostVariance(SCIP_HISTORY *history, SCIP_BRANCHDIR direction)
Definition: history.c:437
SCIP_Real SCIPvarGetImplRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:12771
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:674
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:247
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:214
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16593
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10996
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13777
SCIP_AGGREGATE aggregate
Definition: struct_var.h:224
SCIP_Real lazylb
Definition: struct_var.h:216
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:416
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16035
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:7119
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:1306
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:1758
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16617
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7027
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17196
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:7337
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4201
void SCIPhistoryIncNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, SCIP_Real length)
Definition: history.c:526
SCIP_BOUNDTYPE * SCIPimplicsGetTypes(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3265
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:12767
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16489
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:13675
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17112
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1265
SCIP_RETCODE SCIPdomchgMakeStatic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:1084
SCIP_VBOUNDS * vlbs
Definition: struct_var.h:236
SCIP_RETCODE SCIPdomchgFree(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:983
static SCIP_BDCHGIDX initbdchgidx
Definition: var.c:16122
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:14229
static SCIP_RETCODE varEnsureUbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:375
SCIP_Bool SCIPimplicsContainsImpl(SCIP_IMPLICS *implics, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: implics.c:913
SCIP_Longint lpcount
Definition: struct_stat.h:168
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17728
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:630
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:5801
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11211
int lbchginfossize
Definition: struct_var.h:261
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15134
unsigned int varstatus
Definition: struct_var.h:275
SCIP_RETCODE SCIPvarRelease(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2765
SCIP_Real SCIPvarGetUbOriginal(SCIP_VAR *var)
Definition: var.c:17132
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12167
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:681
SCIP_Real bestrootlpobjval
Definition: struct_var.h:208
SCIP_VARDATA * vardata
Definition: struct_var.h:233
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:5989
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11241
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13826
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15961
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:211
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:9441
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10476
SCIP_RETCODE SCIPvarGetTransformed(SCIP_VAR *origvar, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **transvar)
Definition: var.c:3371
SCIP_HOLECHG * holechgs
Definition: struct_var.h:143
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7881
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17432
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:6546
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:112
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1823
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:16923
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16002
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16552
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:4714
SCIP_VAR * transvar
Definition: struct_var.h:169
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:154
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6098
void SCIPhistoryUnite(SCIP_HISTORY *history, SCIP_HISTORY *addhistory, SCIP_Bool switcheddirs)
Definition: history.c:96
void SCIPmessagePrintWarning(SCIP_MESSAGEHDLR *messagehdlr, const char *formatstr,...)
Definition: message.c:417
#define SCIPsetReallocBufferArray(set, ptr, num)
Definition: set.h:1838
SCIP_Longint SCIPhistoryGetNActiveConflicts(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:542
SCIP_RETCODE SCIPeventCreateLbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:626
SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
Definition: var.c:11292
unsigned int initial
Definition: struct_var.h:269
#define NULL
Definition: lpi_spx1.cpp:137
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13499
SCIP_NEGATE negate
Definition: struct_var.h:226
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4143
static SCIP_RETCODE holelistCreate(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:74
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:7172
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13164
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:159
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16449
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3231
#define REALABS(x)
Definition: def.h:159
int nparentvars
Definition: struct_var.h:256
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17540
SCIP_Real unchangedobj
Definition: struct_var.h:203
SCIP_RETCODE SCIPvarFix(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_CLIQUETABLE *cliquetable, SCIP_Real fixedval, SCIP_Bool *infeasible, SCIP_Bool *fixed)
Definition: var.c:3572
SCIP_HOLELIST * SCIPvarGetHolelistGlobal(SCIP_VAR *var)
Definition: var.c:17186
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:9530
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14570
void SCIPsortPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
internal methods for global SCIP settings
SCIP_RETCODE SCIPvarGetAggregatedObj(SCIP_VAR *var, SCIP_Real *aggrobj)
Definition: var.c:17036
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14047
#define SCIP_CALL(x)
Definition: def.h:306
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17927
SCIP_VBOUNDS * vubs
Definition: struct_var.h:237
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17304
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6008
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17390
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:14749
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:16970
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2279
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13873
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:9249
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5443
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3239
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15473
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17422
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17916
int closestvubidx
Definition: struct_var.h:268
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13961
SCIP_Real SCIPhistoryGetPseudocostCount(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:461
SCIP_Bool SCIPsetIsEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5544
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:10940
SCIP_Real vsidsweight
Definition: struct_stat.h:117
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:7627
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:254
unsigned int nboundchgs
Definition: struct_var.h:140
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17838
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14617
SCIP_RETCODE SCIPvarPrint(SCIP_VAR *var, SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file)
Definition: var.c:2886
unsigned int branchdirection
Definition: struct_var.h:277
int ubchginfossize
Definition: struct_var.h:263
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1585
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5964
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:255
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:326
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13149
int var_probindex
Definition: struct_lp.h:167
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6086
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:419
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16681
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:5774
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10870
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:4937
#define SCIP_UNKNOWN
Definition: def.h:156
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5667
unsigned int vartype
Definition: struct_var.h:274
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17476
int clqcomponentidx
Definition: struct_var.h:247
unsigned int boundchgtype
Definition: struct_var.h:90
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:423
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:14917
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:6221
SCIP_VAR * var
Definition: struct_var.h:89
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:87
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16529
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:8522
#define SCIP_Bool
Definition: def.h:61
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2753
int SCIPvarGetCliqueComponentIdx(SCIP_VAR *var)
Definition: var.c:17646
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:410
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16469
SCIP_Real ub
Definition: struct_var.h:161
unsigned int boundtype
Definition: struct_var.h:91
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17828
unsigned int deletable
Definition: struct_var.h:271
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16253
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15318
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:16891
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5668
SCIP_RETCODE SCIPconsRelease(SCIP_CONS **cons, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: cons.c:6112
void SCIPvarStoreRootSol(SCIP_VAR *var, SCIP_Bool roothaslp)
Definition: var.c:12573
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17553
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17338
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:42094
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15837
SCIP_Bool divingobjchg
Definition: struct_lp.h:355
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17444
SCIP_MULTAGGR multaggr
Definition: struct_var.h:225
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7868
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:421
SCIP_RETCODE SCIPeventCreateGlbChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:580
unsigned int deleted
Definition: struct_var.h:272
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3286
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16572
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3616
int SCIPvarGetNLocksUp(SCIP_VAR *var)
Definition: var.c:3217
#define MAX(x, y)
Definition: tclique_def.h:75
SCIP_Bool SCIPstrToRealValue(const char *str, SCIP_Real *value, char **endptr)
Definition: misc.c:9411
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3247
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:550
SCIP_VAR * SCIPboundchgGetVar(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16459
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11249
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3317
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16507
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17024
unsigned int removable
Definition: struct_var.h:270
#define SCIPsetDebugMsg
Definition: set.h:1870
static SCIP_RETCODE varAddParent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *parentvar)
Definition: var.c:2551
SCIP_Real SCIPvarGetMultaggrUbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8161
unsigned int redundant
Definition: struct_var.h:94
SCIP_Real oldbound
Definition: struct_var.h:107
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17014
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10703
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17778
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13084
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:16901
int closestvlbidx
Definition: struct_var.h:267
#define EPSLE(x, y, eps)
Definition: def.h:162
int nuses
Definition: struct_var.h:257
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15418
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:10489
SCIP_Real SCIPcomputeTwoSampleTTestValue(SCIP_Real meanx, SCIP_Real meany, SCIP_Real variancex, SCIP_Real variancey, SCIP_Real countx, SCIP_Real county)
Definition: misc.c:111
SCIP_RETCODE SCIPvarDelClique(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10742
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:89
void SCIPhistoryUpdatePseudocost(SCIP_HISTORY *history, SCIP_SET *set, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: history.c:159
SCIP_COL * SCIPvarGetCol(SCIP_VAR *var)
Definition: var.c:16880
int probindex
Definition: struct_var.h:250
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:8274
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:2078
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13225
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:16934
SCIP_Longint SCIPhistoryGetNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:616
SCIP_Real * SCIPvarGetImplBounds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17490
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12080
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5942
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:2264
static SCIP_Real adjustedLb(SCIP_SET *set, SCIP_VARTYPE vartype, SCIP_Real lb)
Definition: var.c:1491
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:14489
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:9041
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip.c:40434
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3661
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3236
SCIP * scip
Definition: struct_var.h:200
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:240
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12495
int nlocksup
Definition: struct_var.h:259
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15704
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2178
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17895
const char * SCIPpropGetName(SCIP_PROP *prop)
Definition: prop.c:887
SCIP_BDCHGINFO * SCIPvarGetUbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15760
int conflictubcount
Definition: struct_var.h:266
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3215
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11775
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2190
SCIP_DOM locdom
Definition: struct_var.h:219
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17586
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:9322
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15816
#define SCIP_REAL_MAX
Definition: def.h:136
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6252
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:245
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c:2823
static SCIP_RETCODE varAddLbchginfo(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real oldbound, SCIP_Real newbound, int depth, int pos, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype, SCIP_BOUNDCHGTYPE boundchgtype)
Definition: var.c:401
#define SCIP_DECL_VARDELORIG(x)
Definition: type_var.h:109
SCIP_Real SCIPhistoryGetCutoffSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:655
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:13571
SCIP_RETCODE SCIPvarLoose(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3436
SCIP_Real newbound
Definition: struct_var.h:83
#define SCIP_REAL_MIN
Definition: def.h:137
static SCIP_RETCODE varEventVarFixed(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, int fixeventtype)
Definition: var.c:3477
SCIP_VAR ** parentvars
Definition: struct_var.h:234
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:414
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17461
static SCIP_RETCODE varFreeParents(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2579
SCIP_Real SCIPsetFeasFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6087
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:152
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:7053
#define SCIP_DEFAULT_INFINITY
Definition: def.h:140
static SCIP_RETCODE domchgEnsureHolechgsSize(SCIP_DOMCHG *domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:1198
int SCIPvarGetNLocksDown(SCIP_VAR *var)
Definition: var.c:3162
SCIP_Real SCIPstudentTGetCriticalValue(SCIP_CONFIDENCELEVEL clevel, int df)
Definition: misc.c:94
SCIP_HOLELIST * next
Definition: struct_var.h:51
void SCIPconsCapture(SCIP_CONS *cons)
Definition: cons.c:6100
SCIP_Real SCIPhistoryGetInferenceSum(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:629
#define BMSallocBlockMemorySize(mem, ptr, size)
Definition: memory.h:407
unsigned int boundtype
Definition: struct_var.h:114
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1848
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:706
static const SCIP_Real scalars[]
Definition: lp.c:5563
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:5100
int lpipos
Definition: struct_lp.h:162
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8153
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16499
SCIP_RETCODE SCIPvarColumn(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *prob, SCIP_LP *lp)
Definition: var.c:3402
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:1991
SCIP_Real lazyub
Definition: struct_var.h:217
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17818
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1718
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:135
unsigned int redundant
Definition: struct_var.h:116
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
SCIP_RETCODE SCIPvarGetActiveRepresentatives(SCIP_SET *set, SCIP_VAR **vars, SCIP_Real *scalars, int *nvars, int varssize, SCIP_Real *constant, int *requiredsize, SCIP_Bool mergemultiples)
Definition: var.c:3741
SCIP_Real SCIPnormalCDF(SCIP_Real mean, SCIP_Real variance, SCIP_Real value)
Definition: misc.c:184
SCIP_Bool SCIPvarSignificantPscostDifference(SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR *varx, SCIP_Real fracx, SCIP_VAR *vary, SCIP_Real fracy, SCIP_BRANCHDIR dir, SCIP_CONFIDENCELEVEL clevel, SCIP_Bool onesided)
Definition: var.c:14162
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11298
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13018
SCIP_VAR * var
Definition: struct_var.h:109
public methods for message output
int nrootboundchgsrun
Definition: struct_stat.h:198
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3375
void SCIPmessageFPrintInfo(SCIP_MESSAGEHDLR *messagehdlr, FILE *file, const char *formatstr,...)
Definition: message.c:608
void SCIPvarSetCopyData(SCIP_VAR *var, SCIP_DECL_VARCOPY((*varcopy)))
Definition: var.c:16628
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:8813
SCIP_Real * scalars
Definition: struct_var.h:184
SCIP_IMPLICS * implics
Definition: struct_var.h:238
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16519
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5598
static void holelistFree(SCIP_HOLELIST **holelist, BMS_BLKMEM *blkmem)
Definition: var.c:98
static SCIP_RETCODE varEnsureLbchginfosSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:349
SCIP_VARSTATUS SCIPvarGetStatus(SCIP_VAR *var)
Definition: var.c:16671
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8760
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:146
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:8942
#define SCIP_Real
Definition: def.h:135
internal methods for problem statistics
#define SCIP_EVENTTYPE_VARCHANGED
Definition: type_event.h:113
static SCIP_RETCODE varFree(SCIP_VAR **var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: var.c:2652
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:1222
SCIP_Longint SCIPvarGetNBranchings(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15001
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11584
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17848
#define MIN(x, y)
Definition: memory.c:75
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6041
int parentvarssize
Definition: struct_var.h:255
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:239
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16639
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2288
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11868
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13654
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17631
#define SCIP_INVALID
Definition: def.h:155
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:678
void SCIPsortPtrReal(void **ptrarray, SCIP_Real *realarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), int len)
int SCIPvarGetNUses(SCIP_VAR *var)
Definition: var.c:16562
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11504
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:2468
static SCIP_RETCODE parseBounds(SCIP_SET *set, const char *str, char *type, SCIP_Real *lb, SCIP_Real *ub, char **endptr)
Definition: var.c:2219
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17412
SCIP_RETCODE SCIPeventCreateVarUnlocked(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:536
SCIP_RETCODE SCIPprimalUpdateObjoffset(SCIP_PRIMAL *primal, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp)
Definition: primal.c:441
SCIP_Real branchfactor
Definition: struct_var.h:204
unsigned int donotmultaggr
Definition: struct_var.h:273
#define SCIP_Longint
Definition: def.h:120
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17278
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17860
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6241
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13364
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16849
SCIP_Real nlpsol
Definition: struct_var.h:210
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:161
static SCIP_RETCODE varEnsureParentvarsSize(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, int num)
Definition: var.c:2527
SCIP_Real SCIPvarGetAvgCutoffs(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15559
SCIP_Real lb
Definition: struct_var.h:160
SCIP_VAR * var
Definition: struct_lp.h:149
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5986
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:8651
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16717
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8029
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2792
SCIP_DOM glbdom
Definition: struct_var.h:218
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5406
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:642
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2669
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:6259
SCIP_Bool collectvarhistory
Definition: struct_stat.h:255
SCIP_VAR * negatedvar
Definition: struct_var.h:235
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16819
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3337
SCIP_Real newbound
Definition: struct_var.h:108
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17232
int nlocksdown
Definition: struct_var.h:258
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3295
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8222
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15690
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6069
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16694
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6329
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:406
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17242
unsigned int delglobalstructs
Definition: struct_var.h:279
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6263
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17808
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:17693
SCIP_Real rootsol
Definition: struct_var.h:205
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2435
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2846
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13530
SCIP_HISTORY * history
Definition: struct_var.h:243
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16655
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15179
int nrootintfixingsrun
Definition: struct_stat.h:200
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:392
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:11953
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
#define SCIP_CALL_ABORT(x)
Definition: def.h:285
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17618
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3274
SCIP_ORIGINAL original
Definition: struct_var.h:222
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3811
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16869
#define SCIP_ALLOC(x)
Definition: def.h:317
#define SCIPABORT()
Definition: def.h:278
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16743
SCIP_RETCODE SCIPeventCreateGubChanged(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_Real oldbound, SCIP_Real newbound)
Definition: event.c:603
void SCIPhistoryFree(SCIP_HISTORY **history, BMS_BLKMEM *blkmem)
Definition: history.c:55
SCIP_Real SCIPvarGetMultaggrLbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:7963
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:7945
unsigned int applied
Definition: struct_var.h:93
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16773
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:66
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10665
SCIP_HOLELIST ** ptr
Definition: struct_var.h:57
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16809
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:412
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:142
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5704
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16582
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16144
SCIP_COL * col
Definition: struct_var.h:223
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5527
SCIP_Real left
Definition: struct_var.h:43
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8056
SCIP_RETCODE SCIPdomchgAddBoundchg(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_VAR *var, SCIP_Real newbound, SCIP_BOUNDTYPE boundtype, SCIP_BOUNDCHGTYPE boundchgtype, SCIP_Real lpsolval, SCIP_VAR *infervar, SCIP_CONS *infercons, SCIP_PROP *inferprop, int inferinfo, SCIP_BOUNDTYPE inferboundtype)
Definition: var.c:1345
SCIP_Bool SCIPvarMayRoundUp(SCIP_VAR *var)
Definition: var.c:3280
#define EPSZ(x, eps)
Definition: def.h:165
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:444
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11059
SCIP_Bool SCIPvarMayRoundDown(SCIP_VAR *var)
Definition: var.c:3272
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:914
SCIP callable library.
SCIP_Bool SCIPsetIsFeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6052
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:13993
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16839
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:241
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14298
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1507
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16707
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:5460
SCIP_Real scalar
Definition: struct_var.h:175
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17798
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10725