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-2018 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,
597  NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_LOWER, SCIP_BOUNDCHGTYPE_BRANCHING) );
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,
664  NULL, NULL, NULL, 0, SCIP_BOUNDTYPE_UPPER, SCIP_BOUNDCHGTYPE_BRANCHING) );
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 
1976  stat->nvaridx++;
1977 
1978  /* create branching and inference history entries */
1979  SCIP_CALL( SCIPhistoryCreate(&(*var)->history, blkmem) );
1980  SCIP_CALL( SCIPhistoryCreate(&(*var)->historycrun, blkmem) );
1981 
1982  /* the value based history is only created on demand */
1983  (*var)->valuehistory = NULL;
1984 
1985  return SCIP_OKAY;
1986 }
1987 
1988 /** creates and captures an original problem variable; an integer variable with bounds
1989  * zero and one is automatically converted into a binary variable
1990  */
1992  SCIP_VAR** var, /**< pointer to variable data */
1993  BMS_BLKMEM* blkmem, /**< block memory */
1994  SCIP_SET* set, /**< global SCIP settings */
1995  SCIP_STAT* stat, /**< problem statistics */
1996  const char* name, /**< name of variable, or NULL for automatic name creation */
1997  SCIP_Real lb, /**< lower bound of variable */
1998  SCIP_Real ub, /**< upper bound of variable */
1999  SCIP_Real obj, /**< objective function value */
2000  SCIP_VARTYPE vartype, /**< type of variable */
2001  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2002  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2003  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2004  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2005  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2006  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2007  SCIP_VARDATA* vardata /**< user data for this specific variable */
2008  )
2009 {
2010  assert(var != NULL);
2011  assert(blkmem != NULL);
2012  assert(stat != NULL);
2013 
2014  /* create variable */
2015  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2016  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2017 
2018  /* set variable status and data */
2019  (*var)->varstatus = SCIP_VARSTATUS_ORIGINAL; /*lint !e641*/
2020  (*var)->data.original.origdom.holelist = NULL;
2021  (*var)->data.original.origdom.lb = lb;
2022  (*var)->data.original.origdom.ub = ub;
2023  (*var)->data.original.transvar = NULL;
2024 
2025  /* capture variable */
2026  SCIPvarCapture(*var);
2027 
2028  return SCIP_OKAY;
2029 }
2030 
2031 /** creates and captures a loose variable belonging to the transformed problem; an integer variable with bounds
2032  * zero and one is automatically converted into a binary variable
2033  */
2035  SCIP_VAR** var, /**< pointer to variable data */
2036  BMS_BLKMEM* blkmem, /**< block memory */
2037  SCIP_SET* set, /**< global SCIP settings */
2038  SCIP_STAT* stat, /**< problem statistics */
2039  const char* name, /**< name of variable, or NULL for automatic name creation */
2040  SCIP_Real lb, /**< lower bound of variable */
2041  SCIP_Real ub, /**< upper bound of variable */
2042  SCIP_Real obj, /**< objective function value */
2043  SCIP_VARTYPE vartype, /**< type of variable */
2044  SCIP_Bool initial, /**< should var's column be present in the initial root LP? */
2045  SCIP_Bool removable, /**< is var's column removable from the LP (due to aging or cleanup)? */
2046  SCIP_DECL_VARDELORIG ((*vardelorig)), /**< frees user data of original variable, or NULL */
2047  SCIP_DECL_VARTRANS ((*vartrans)), /**< creates transformed user data by transforming original user data, or NULL */
2048  SCIP_DECL_VARDELTRANS ((*vardeltrans)), /**< frees user data of transformed variable, or NULL */
2049  SCIP_DECL_VARCOPY ((*varcopy)), /**< copies variable data if wanted to subscip, or NULL */
2050  SCIP_VARDATA* vardata /**< user data for this specific variable */
2051  )
2052 {
2053  assert(var != NULL);
2054  assert(blkmem != NULL);
2055 
2056  /* create variable */
2057  SCIP_CALL( varCreate(var, blkmem, set, stat, name, lb, ub, obj, vartype, initial, removable,
2058  varcopy, vardelorig, vartrans, vardeltrans, vardata) );
2059 
2060  /* create event filter for transformed variable */
2061  SCIP_CALL( SCIPeventfilterCreate(&(*var)->eventfilter, blkmem) );
2062 
2063  /* set variable status and data */
2064  (*var)->varstatus = SCIP_VARSTATUS_LOOSE; /*lint !e641*/
2065 
2066  /* capture variable */
2067  SCIPvarCapture(*var);
2068 
2069  return SCIP_OKAY;
2070 }
2071 
2072 /** copies and captures a variable from source to target SCIP; an integer variable with bounds zero and one is
2073  * automatically converted into a binary variable; in case the variable data cannot be copied the variable is not
2074  * copied at all
2075  */
2077  SCIP_VAR** var, /**< pointer to store the target variable */
2078  BMS_BLKMEM* blkmem, /**< block memory */
2079  SCIP_SET* set, /**< global SCIP settings */
2080  SCIP_STAT* stat, /**< problem statistics */
2081  SCIP* sourcescip, /**< source SCIP data structure */
2082  SCIP_VAR* sourcevar, /**< source variable */
2083  SCIP_HASHMAP* varmap, /**< a hashmap to store the mapping of source variables corresponding
2084  * target variables */
2085  SCIP_HASHMAP* consmap, /**< a hashmap to store the mapping of source constraints to the corresponding
2086  * target constraints */
2087  SCIP_Bool global /**< should global or local bounds be used? */
2088  )
2089 {
2090  SCIP_VARDATA* targetdata;
2091  SCIP_RESULT result;
2092  SCIP_Real lb;
2093  SCIP_Real ub;
2094 
2095  assert(set != NULL);
2096  assert(blkmem != NULL);
2097  assert(stat != NULL);
2098  assert(sourcescip != NULL);
2099  assert(sourcevar != NULL);
2100  assert(var != NULL);
2101  assert(set->stage == SCIP_STAGE_PROBLEM);
2102  assert(varmap != NULL);
2103  assert(consmap != NULL);
2104 
2105  /** @todo copy hole lists */
2106  assert(global || SCIPvarGetHolelistLocal(sourcevar) == NULL);
2107  assert(!global || SCIPvarGetHolelistGlobal(sourcevar) == NULL);
2108 
2109  result = SCIP_DIDNOTRUN;
2110  targetdata = NULL;
2111 
2112  if( SCIPvarGetStatus(sourcevar) == SCIP_VARSTATUS_ORIGINAL )
2113  {
2114  lb = SCIPvarGetLbOriginal(sourcevar);
2115  ub = SCIPvarGetUbOriginal(sourcevar);
2116  }
2117  else
2118  {
2119  lb = global ? SCIPvarGetLbGlobal(sourcevar) : SCIPvarGetLbLocal(sourcevar);
2120  ub = global ? SCIPvarGetUbGlobal(sourcevar) : SCIPvarGetUbLocal(sourcevar);
2121  }
2122 
2123  /* creates and captures the variable in the target SCIP and initialize callback methods and variable data to NULL */
2124  SCIP_CALL( SCIPvarCreateOriginal(var, blkmem, set, stat, SCIPvarGetName(sourcevar),
2125  lb, ub, SCIPvarGetObj(sourcevar), SCIPvarGetType(sourcevar),
2126  SCIPvarIsInitial(sourcevar), SCIPvarIsRemovable(sourcevar),
2127  NULL, NULL, NULL, NULL, NULL) );
2128  assert(*var != NULL);
2129 
2130  /* directly copy donotmultaggr flag */
2131  (*var)->donotmultaggr = sourcevar->donotmultaggr;
2132 
2133  /* insert variable into mapping between source SCIP and the target SCIP */
2134  assert(!SCIPhashmapExists(varmap, sourcevar));
2135  SCIP_CALL( SCIPhashmapInsert(varmap, sourcevar, *var) );
2136 
2137  /* in case there exists variable data and the variable data copy callback, try to copy variable data */
2138  if( sourcevar->vardata != NULL && sourcevar->varcopy != NULL )
2139  {
2140  SCIP_CALL( sourcevar->varcopy(set->scip, sourcescip, sourcevar, sourcevar->vardata,
2141  varmap, consmap, (*var), &targetdata, &result) );
2142 
2143  /* evaluate result */
2144  if( result != SCIP_DIDNOTRUN && result != SCIP_SUCCESS )
2145  {
2146  SCIPerrorMessage("variable data copying method returned invalid result <%d>\n", result);
2147  return SCIP_INVALIDRESULT;
2148  }
2149 
2150  assert(targetdata == NULL || result == SCIP_SUCCESS);
2151 
2152  /* if copying was successful, add the created variable data to the variable as well as all callback methods */
2153  if( result == SCIP_SUCCESS )
2154  {
2155  (*var)->varcopy = sourcevar->varcopy;
2156  (*var)->vardelorig = sourcevar->vardelorig;
2157  (*var)->vartrans = sourcevar->vartrans;
2158  (*var)->vardeltrans = sourcevar->vardeltrans;
2159  (*var)->vardata = targetdata;
2160  }
2161  }
2162 
2163  /* we initialize histories of the variables by copying the source variable-information */
2164  if( set->history_allowtransfer )
2165  {
2166  SCIPvarMergeHistories((*var), sourcevar, stat);
2167  }
2168 
2169  /* in case the copying was successfully, add the created variable data to the variable as well as all callback
2170  * methods
2171  */
2172  if( result == SCIP_SUCCESS )
2173  {
2174  (*var)->varcopy = sourcevar->varcopy;
2175  (*var)->vardelorig = sourcevar->vardelorig;
2176  (*var)->vartrans = sourcevar->vartrans;
2177  (*var)->vardeltrans = sourcevar->vardeltrans;
2178  (*var)->vardata = targetdata;
2179  }
2180 
2181  SCIPsetDebugMsg(set, "created copy <%s> of variable <%s>\n", SCIPvarGetName(*var), SCIPvarGetName(sourcevar));
2182 
2183  return SCIP_OKAY;
2184 }
2185 
2186 /** parse given string for a SCIP_Real bound */
2187 static
2189  SCIP_SET* set, /**< global SCIP settings */
2190  const char* str, /**< string to parse */
2191  SCIP_Real* value, /**< pointer to store the parsed value */
2192  char** endptr /**< pointer to store the final string position if successfully parsed */
2193  )
2194 {
2195  /* first check for infinity value */
2196  if( strncmp(str, "+inf", 4) == 0 )
2197  {
2198  *value = SCIPsetInfinity(set);
2199  (*endptr) = (char*)str + 4;
2200  }
2201  else if( strncmp(str, "-inf", 4) == 0 )
2202  {
2203  *value = -SCIPsetInfinity(set);
2204  (*endptr) = (char*)str + 4;
2205  }
2206  else
2207  {
2208  if( !SCIPstrToRealValue(str, value, endptr) )
2209  return SCIP_READERROR;
2210  }
2211 
2212  return SCIP_OKAY;
2213 }
2214 
2215 /** parse the characters as bounds */
2216 static
2218  SCIP_SET* set, /**< global SCIP settings */
2219  const char* str, /**< string to parse */
2220  char* type, /**< bound type (global, local, or lazy) */
2221  SCIP_Real* lb, /**< pointer to store the lower bound */
2222  SCIP_Real* ub, /**< pointer to store the upper bound */
2223  char** endptr /**< pointer to store the final string position if successfully parsed (or NULL if an error occured) */
2224  )
2225 {
2226  char token[SCIP_MAXSTRLEN];
2227  char* tmpend;
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, &tmpend) );
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  int k;
3762 
3763  SCIP_VAR** tmpvars;
3764  SCIP_VAR** multvars;
3765  SCIP_Real* tmpscalars;
3766  SCIP_Real* multscalars;
3767  int tmpvarssize;
3768  int ntmpvars;
3769  int nmultvars;
3770 
3771  SCIP_VAR* multvar;
3772  SCIP_Real multscalar;
3773  SCIP_Real multconstant;
3774  int pos;
3775 
3776  int noldtmpvars;
3777 
3778  SCIP_VAR** tmpvars2;
3779  SCIP_Real* tmpscalars2;
3780  int tmpvarssize2;
3781  int ntmpvars2;
3782 
3783  SCIP_Bool sortagain = FALSE;
3784 
3785  assert(set != NULL);
3786  assert(nvars != NULL);
3787  assert(scalars != NULL || *nvars == 0);
3788  assert(constant != NULL);
3789  assert(requiredsize != NULL);
3790  assert(*nvars <= varssize);
3791 
3792  *requiredsize = 0;
3793 
3794  if( *nvars == 0 )
3795  return SCIP_OKAY;
3796 
3797  assert(vars != NULL);
3798 
3799  /* handle the "easy" case of just one variable and avoid memory allocation if the variable is already active */
3800  if( *nvars == 1 && (vars[0]->varstatus == ((int) SCIP_VARSTATUS_COLUMN) || vars[0]->varstatus == ((int) SCIP_VARSTATUS_LOOSE)) )
3801  {
3802  *requiredsize = 1;
3803 
3804  return SCIP_OKAY;
3805  }
3806 
3807  nactivevars = 0;
3808  activeconstant = 0.0;
3809  activeconstantinf = FALSE;
3810  activevarssize = (*nvars) * 2;
3811  ntmpvars = *nvars;
3812  tmpvarssize = *nvars;
3813 
3814  tmpvarssize2 = 1;
3815 
3816  /* allocate temporary memory */
3817  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpvars2, tmpvarssize2) );
3818  SCIP_CALL( SCIPsetAllocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3819  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
3820  SCIP_CALL( SCIPsetAllocBufferArray(set, &activescalars, activevarssize) );
3821  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
3822  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpscalars, scalars, ntmpvars) );
3823 
3824  /* to avoid unnecessary expanding of variable arrays while disaggregating several variables multiple times combine same variables
3825  * first, first get all corresponding variables with status loose, column, multaggr or fixed
3826  */
3827  for( v = ntmpvars - 1; v >= 0; --v )
3828  {
3829  var = tmpvars[v];
3830  scalar = tmpscalars[v];
3831 
3832  assert(var != NULL);
3833  /* transforms given variable, scalar and constant to the corresponding active, fixed, or
3834  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed
3835  * variable, "scalar" will be 0.0 and the value of the sum will be stored in "constant".
3836  */
3837  SCIP_CALL( SCIPvarGetProbvarSum(&var, set, &scalar, &activeconstant) );
3838  assert(var != NULL);
3839 
3840  assert(SCIPsetIsInfinity(set, activeconstant) == (activeconstant == SCIPsetInfinity(set))); /*lint !e777*/
3841  assert(SCIPsetIsInfinity(set, -activeconstant) == (activeconstant == -SCIPsetInfinity(set))); /*lint !e777*/
3842 
3843  activeconstantinf = SCIPsetIsInfinity(set, activeconstant) || SCIPsetIsInfinity(set, -activeconstant);
3844 
3845  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3846  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3849 
3850  tmpvars[v] = var;
3851  tmpscalars[v] = scalar;
3852  }
3853  noldtmpvars = ntmpvars;
3854 
3855  /* sort all variables to combine equal variables easily */
3856  SCIPsortPtrReal((void**)tmpvars, tmpscalars, SCIPvarComp, noldtmpvars);
3857  ntmpvars = 0;
3858  for( v = 1; v < noldtmpvars; ++v )
3859  {
3860  /* combine same variables */
3861  if( SCIPvarCompare(tmpvars[v], tmpvars[ntmpvars]) == 0 )
3862  {
3863  tmpscalars[ntmpvars] += tmpscalars[v];
3864  }
3865  else
3866  {
3867  ++ntmpvars;
3868  if( v > ntmpvars )
3869  {
3870  tmpscalars[ntmpvars] = tmpscalars[v];
3871  tmpvars[ntmpvars] = tmpvars[v];
3872  }
3873  }
3874  }
3875  ++ntmpvars;
3876 
3877 #ifdef SCIP_MORE_DEBUG
3878  for( v = 1; v < ntmpvars; ++v )
3879  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
3880 #endif
3881 
3882 
3883  /* collect for each variable the representation in active variables */
3884  while( ntmpvars >= 1 )
3885  {
3886  --ntmpvars;
3887  ntmpvars2 = 0;
3888  var = tmpvars[ntmpvars];
3889  scalar = tmpscalars[ntmpvars];
3890 
3891  assert(var != NULL);
3892 
3893  /* TODO: maybe we should test here on SCIPsetIsZero() instead of 0.0 */
3894  if( scalar == 0.0 )
3895  continue;
3896 
3897  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3898  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3901 
3902  switch( SCIPvarGetStatus(var) )
3903  {
3904  case SCIP_VARSTATUS_LOOSE:
3905  case SCIP_VARSTATUS_COLUMN:
3906  /* x = a*y + c */
3907  if( nactivevars >= activevarssize )
3908  {
3909  activevarssize *= 2;
3910  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
3911  SCIP_CALL( SCIPsetReallocBufferArray(set, &activescalars, activevarssize) );
3912  assert(nactivevars < activevarssize);
3913  }
3914  activevars[nactivevars] = var;
3915  activescalars[nactivevars] = scalar;
3916  nactivevars++;
3917  break;
3918 
3920  /* x = a_1*y_1 + ... + a_n*y_n + c */
3921  nmultvars = var->data.multaggr.nvars;
3922  multvars = var->data.multaggr.vars;
3923  multscalars = var->data.multaggr.scalars;
3924  sortagain = TRUE;
3925 
3926  if( nmultvars + ntmpvars > tmpvarssize )
3927  {
3928  while( nmultvars + ntmpvars > tmpvarssize )
3929  tmpvarssize *= 2;
3930  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
3931  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars, tmpvarssize) );
3932  assert(nmultvars + ntmpvars <= tmpvarssize);
3933  }
3934 
3935  if( nmultvars > tmpvarssize2 )
3936  {
3937  while( nmultvars > tmpvarssize2 )
3938  tmpvarssize2 *= 2;
3939  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars2, tmpvarssize2) );
3940  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpscalars2, tmpvarssize2) );
3941  assert(nmultvars <= tmpvarssize2);
3942  }
3943 
3944  --nmultvars;
3945 
3946  for( ; nmultvars >= 0; --nmultvars )
3947  {
3948  multvar = multvars[nmultvars];
3949  multscalar = multscalars[nmultvars];
3950  multconstant = 0;
3951 
3952  assert(multvar != NULL);
3953  SCIP_CALL( SCIPvarGetProbvarSum(&multvar, set, &multscalar, &multconstant) );
3954  assert(multvar != NULL);
3955 
3956  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE
3957  || SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN
3960 
3961  if( !activeconstantinf )
3962  {
3963  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
3964 
3965  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
3966  {
3967  assert(scalar != 0.0);
3968  if( scalar * multconstant > 0.0 )
3969  {
3970  activeconstant = SCIPsetInfinity(set);
3971  activeconstantinf = TRUE;
3972  }
3973  else
3974  {
3975  activeconstant = -SCIPsetInfinity(set);
3976  activeconstantinf = TRUE;
3977  }
3978  }
3979  else
3980  activeconstant += scalar * multconstant;
3981  }
3982 #ifndef NDEBUG
3983  else
3984  {
3985  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
3986  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3987  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
3988  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
3989  }
3990 #endif
3991 
3992  if( SCIPsortedvecFindPtr((void**)tmpvars, SCIPvarComp, multvar, ntmpvars, &pos) )
3993  {
3994  assert(SCIPvarCompare(tmpvars[pos], multvar) == 0);
3995  tmpscalars[pos] += scalar * multscalar;
3996  }
3997  else
3998  {
3999  tmpvars2[ntmpvars2] = multvar;
4000  tmpscalars2[ntmpvars2] = scalar * multscalar;
4001  ++(ntmpvars2);
4002  assert(ntmpvars2 <= tmpvarssize2);
4003  }
4004  }
4005 
4006  if( ntmpvars2 > 0 )
4007  {
4008  /* sort all variables to combine equal variables easily */
4009  SCIPsortPtrReal((void**)tmpvars2, tmpscalars2, SCIPvarComp, ntmpvars2);
4010  pos = 0;
4011  for( v = 1; v < ntmpvars2; ++v )
4012  {
4013  /* combine same variables */
4014  if( SCIPvarCompare(tmpvars2[v], tmpvars2[pos]) == 0 )
4015  {
4016  tmpscalars2[pos] += tmpscalars2[v];
4017  }
4018  else
4019  {
4020  ++pos;
4021  if( v > pos )
4022  {
4023  tmpscalars2[pos] = tmpscalars2[v];
4024  tmpvars2[pos] = tmpvars2[v];
4025  }
4026  }
4027  }
4028  ntmpvars2 = pos + 1;
4029 #ifdef SCIP_MORE_DEBUG
4030  for( v = 1; v < ntmpvars2; ++v )
4031  {
4032  assert(SCIPvarCompare(tmpvars2[v], tmpvars2[v-1]) > 0);
4033  }
4034  for( v = 1; v < ntmpvars; ++v )
4035  {
4036  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4037  }
4038 #endif
4039  v = ntmpvars - 1;
4040  k = ntmpvars2 - 1;
4041  pos = ntmpvars + ntmpvars2 - 1;
4042  ntmpvars += ntmpvars2;
4043 
4044  while( v >= 0 && k >= 0 )
4045  {
4046  assert(pos >= 0);
4047  assert(SCIPvarCompare(tmpvars[v], tmpvars2[k]) != 0);
4048  if( SCIPvarCompare(tmpvars[v], tmpvars2[k]) >= 0 )
4049  {
4050  tmpvars[pos] = tmpvars[v];
4051  tmpscalars[pos] = tmpscalars[v];
4052  --v;
4053  }
4054  else
4055  {
4056  tmpvars[pos] = tmpvars2[k];
4057  tmpscalars[pos] = tmpscalars2[k];
4058  --k;
4059  }
4060  --pos;
4061  assert(pos >= 0);
4062  }
4063  while( v >= 0 )
4064  {
4065  assert(pos >= 0);
4066  tmpvars[pos] = tmpvars[v];
4067  tmpscalars[pos] = tmpscalars[v];
4068  --v;
4069  --pos;
4070  }
4071  while( k >= 0 )
4072  {
4073  assert(pos >= 0);
4074  tmpvars[pos] = tmpvars2[k];
4075  tmpscalars[pos] = tmpscalars2[k];
4076  --k;
4077  --pos;
4078  }
4079  }
4080 #ifdef SCIP_MORE_DEBUG
4081  for( v = 1; v < ntmpvars; ++v )
4082  {
4083  assert(SCIPvarCompare(tmpvars[v], tmpvars[v-1]) > 0);
4084  }
4085 #endif
4086 
4087  if( !activeconstantinf )
4088  {
4089  assert(!SCIPsetIsInfinity(set, scalar) && !SCIPsetIsInfinity(set, -scalar));
4090 
4091  multconstant = SCIPvarGetMultaggrConstant(var);
4092 
4093  if( SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant) )
4094  {
4095  assert(scalar != 0.0);
4096  if( scalar * multconstant > 0.0 )
4097  {
4098  activeconstant = SCIPsetInfinity(set);
4099  activeconstantinf = TRUE;
4100  }
4101  else
4102  {
4103  activeconstant = -SCIPsetInfinity(set);
4104  activeconstantinf = TRUE;
4105  }
4106  }
4107  else
4108  activeconstant += scalar * multconstant;
4109  }
4110 #ifndef NDEBUG
4111  else
4112  {
4113  multconstant = SCIPvarGetMultaggrConstant(var);
4114  assert(!SCIPsetIsInfinity(set, activeconstant) || !(scalar * multconstant < 0.0 &&
4115  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4116  assert(!SCIPsetIsInfinity(set, -activeconstant) || !(scalar * multconstant > 0.0 &&
4117  (SCIPsetIsInfinity(set, multconstant) || SCIPsetIsInfinity(set, -multconstant))));
4118  }
4119 #endif
4120  break;
4121 
4122  case SCIP_VARSTATUS_FIXED:
4126  default:
4127  /* case x = c, but actually we should not be here, since SCIPvarGetProbvarSum() returns a scalar of 0.0 for
4128  * fixed variables and is handled already
4129  */
4130  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_FIXED);
4131  assert(SCIPsetIsZero(set, var->glbdom.lb) && SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub));
4132  }
4133  }
4134 
4135  if( mergemultiples )
4136  {
4137  if( sortagain )
4138  {
4139  /* sort variable and scalar array by variable index */
4140  SCIPsortPtrReal((void**)activevars, activescalars, SCIPvarComp, nactivevars);
4141 
4142  /* eliminate duplicates and count required size */
4143  v = nactivevars - 1;
4144  while( v > 0 )
4145  {
4146  /* combine both variable since they are the same */
4147  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
4148  {
4149  if( activescalars[v - 1] + activescalars[v] != 0.0 )
4150  {
4151  activescalars[v - 1] += activescalars[v];
4152  --nactivevars;
4153  activevars[v] = activevars[nactivevars];
4154  activescalars[v] = activescalars[nactivevars];
4155  }
4156  else
4157  {
4158  --nactivevars;
4159  activevars[v] = activevars[nactivevars];
4160  activescalars[v] = activescalars[nactivevars];
4161  --nactivevars;
4162  --v;
4163  activevars[v] = activevars[nactivevars];
4164  activescalars[v] = activescalars[nactivevars];
4165  }
4166  }
4167  --v;
4168  }
4169  }
4170  /* the variables were added in reverse order, we revert the order now;
4171  * this should not be necessary, but not doing this changes the behavior sometimes
4172  */
4173  else
4174  {
4175  SCIP_VAR* tmpvar;
4176  SCIP_Real tmpscalar;
4177 
4178  for( v = 0; v < nactivevars / 2; ++v )
4179  {
4180  tmpvar = activevars[v];
4181  tmpscalar = activescalars[v];
4182  activevars[v] = activevars[nactivevars - 1 - v];
4183  activescalars[v] = activescalars[nactivevars - 1 - v];
4184  activevars[nactivevars - 1 - v] = tmpvar;
4185  activescalars[nactivevars - 1 - v] = tmpscalar;
4186  }
4187  }
4188  }
4189  *requiredsize = nactivevars;
4190 
4191  if( varssize >= *requiredsize )
4192  {
4193  assert(vars != NULL);
4194 
4195  *nvars = *requiredsize;
4196 
4197  if( !SCIPsetIsInfinity(set, *constant) && !SCIPsetIsInfinity(set, -(*constant)) )
4198  {
4199  /* if the activeconstant is infinite, the constant pointer gets the same value, otherwise add the value */
4200  if( activeconstantinf )
4201  (*constant) = activeconstant;
4202  else
4203  (*constant) += activeconstant;
4204  }
4205 #ifndef NDEBUG
4206  else
4207  {
4208  assert(!SCIPsetIsInfinity(set, (*constant)) || !SCIPsetIsInfinity(set, -activeconstant));
4209  assert(!SCIPsetIsInfinity(set, -(*constant)) || !SCIPsetIsInfinity(set, activeconstant));
4210  }
4211 #endif
4212 
4213  /* copy active variable and scalar array to the given arrays */
4214  for( v = 0; v < *nvars; ++v )
4215  {
4216  vars[v] = activevars[v];
4217  scalars[v] = activescalars[v]; /*lint !e613*/
4218  }
4219  }
4220 
4221  assert(SCIPsetIsInfinity(set, *constant) == ((*constant) == SCIPsetInfinity(set))); /*lint !e777*/
4222  assert(SCIPsetIsInfinity(set, -(*constant)) == ((*constant) == -SCIPsetInfinity(set))); /*lint !e777*/
4223 
4224  SCIPsetFreeBufferArray(set, &tmpscalars);
4225  SCIPsetFreeBufferArray(set, &tmpvars);
4226  SCIPsetFreeBufferArray(set, &activescalars);
4227  SCIPsetFreeBufferArray(set, &activevars);
4228  SCIPsetFreeBufferArray(set, &tmpscalars2);
4229  SCIPsetFreeBufferArray(set, &tmpvars2);
4230 
4231  return SCIP_OKAY;
4232 }
4233 
4234 
4235 /** flattens aggregation graph of multi-aggregated variable in order to avoid exponential recursion later on */
4237  SCIP_VAR* var, /**< problem variable */
4238  BMS_BLKMEM* blkmem, /**< block memory */
4239  SCIP_SET* set /**< global SCIP settings */
4240  )
4241 {
4242  SCIP_Real multconstant;
4243  int multvarssize;
4244  int nmultvars;
4245  int multrequiredsize;
4246 
4247  assert( var != NULL );
4248  assert( SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR );
4249  assert(var->scip == set->scip);
4250 
4251  multconstant = var->data.multaggr.constant;
4252  nmultvars = var->data.multaggr.nvars;
4253  multvarssize = var->data.multaggr.varssize;
4254 
4255  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4256 
4257  if( multrequiredsize > multvarssize )
4258  {
4259  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.vars), multvarssize, multrequiredsize) );
4260  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &(var->data.multaggr.scalars), multvarssize, multrequiredsize) );
4261  multvarssize = multrequiredsize;
4262  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, var->data.multaggr.vars, var->data.multaggr.scalars, &nmultvars, multvarssize, &multconstant, &multrequiredsize, TRUE) );
4263  assert( multrequiredsize <= multvarssize );
4264  }
4265  /**@note After the flattening the multi aggregation might resolve to be in fact an aggregation (or even a fixing?).
4266  * This issue is not resolved right now, since var->data.multaggr.nvars < 2 should not cause troubles. However, one
4267  * may loose performance hereby, since aggregated variables are easier to handle.
4268  *
4269  * Note, that there are two cases where SCIPvarFlattenAggregationGraph() is called: The easier one is that it is
4270  * called while installing the multi-aggregation. in principle, the described issue could be handled straightforward
4271  * in this case by aggregating or fixing the variable instead. The more complicated case is the one, when the
4272  * multi-aggregation is used, e.g., in linear presolving (and the variable is already declared to be multi-aggregated).
4273  *
4274  * By now, it is not allowed to fix or aggregate multi-aggregated variables which would be necessary in this case.
4275  *
4276  * The same issue appears in the SCIPvarGetProbvar...() methods.
4277  */
4278 
4279  var->data.multaggr.constant = multconstant;
4280  var->data.multaggr.nvars = nmultvars;
4281  var->data.multaggr.varssize = multvarssize;
4282 
4283  return SCIP_OKAY;
4284 }
4285 
4286 /** merge two variable histories together; a typical use case is that \p othervar is an image of the target variable
4287  * in a SCIP copy. Method should be applied with care, especially because no internal checks are performed whether
4288  * the history merge is reasonable
4289  *
4290  * @note Do not use this method if the two variables originate from two SCIP's with different objective functions, since
4291  * this corrupts the variable pseudo costs
4292  * @note Apply with care; no internal checks are performed if the two variables should be merged
4293  */
4295  SCIP_VAR* targetvar, /**< the variable that should contain both histories afterwards */
4296  SCIP_VAR* othervar, /**< the variable whose history is to be merged with that of the target variable */
4297  SCIP_STAT* stat /**< problem statistics */
4298  )
4299 {
4300  /* merge only the history of the current run into the target history */
4301  SCIPhistoryUnite(targetvar->history, othervar->historycrun, FALSE);
4302 
4303  /* apply the changes also to the global history */
4304  SCIPhistoryUnite(stat->glbhistory, othervar->historycrun, FALSE);
4305 }
4306 
4307 /** sets the history of a variable; this method is typically used within reoptimization to keep and update the variable
4308  * history over several iterations
4309  */
4310 void SCIPvarSetHistory(
4311  SCIP_VAR* var, /**< variable */
4312  SCIP_HISTORY* history, /**< the history which is to set */
4313  SCIP_STAT* stat /**< problem statistics */
4314  )
4315 {
4316  /* merge only the history of the current run into the target history */
4317  SCIPhistoryUnite(var->history, history, FALSE);
4318 
4319  /* apply the changes also to the global history */
4320  SCIPhistoryUnite(stat->glbhistory, history, FALSE);
4321 }
4322 
4323 /** tightens the bounds of both variables in aggregation x = a*y + c */
4324 static
4326  SCIP_VAR* var, /**< problem variable */
4327  BMS_BLKMEM* blkmem, /**< block memory */
4328  SCIP_SET* set, /**< global SCIP settings */
4329  SCIP_STAT* stat, /**< problem statistics */
4330  SCIP_PROB* transprob, /**< tranformed problem data */
4331  SCIP_PROB* origprob, /**< original problem data */
4332  SCIP_PRIMAL* primal, /**< primal data */
4333  SCIP_TREE* tree, /**< branch and bound tree */
4334  SCIP_REOPT* reopt, /**< reoptimization data structure */
4335  SCIP_LP* lp, /**< current LP data */
4336  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4337  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4338  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4339  SCIP_VAR* aggvar, /**< variable y in aggregation x = a*y + c */
4340  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4341  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4342  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4343  SCIP_Bool* fixed /**< pointer to store whether the variables were fixed */
4344  )
4345 {
4346  SCIP_Real varlb;
4347  SCIP_Real varub;
4348  SCIP_Real aggvarlb;
4349  SCIP_Real aggvarub;
4350  SCIP_Bool aggvarbdschanged;
4351 
4352  assert(var != NULL);
4353  assert(var->scip == set->scip);
4354  assert(aggvar != NULL);
4355  assert(!SCIPsetIsZero(set, scalar));
4356  assert(infeasible != NULL);
4357  assert(fixed != NULL);
4358 
4359  *infeasible = FALSE;
4360  *fixed = FALSE;
4361 
4362  SCIPsetDebugMsg(set, "updating bounds of variables in aggregation <%s> == %g*<%s> %+g\n", var->name, scalar, aggvar->name, constant);
4363  SCIPsetDebugMsg(set, " old bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4364  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4365 
4366  /* loop as long additional changes may be found */
4367  do
4368  {
4369  aggvarbdschanged = FALSE;
4370 
4371  /* update the bounds of the aggregated variable x in x = a*y + c */
4372  if( scalar > 0.0 )
4373  {
4374  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4375  varlb = -SCIPsetInfinity(set);
4376  else
4377  varlb = aggvar->glbdom.lb * scalar + constant;
4378  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4379  varub = SCIPsetInfinity(set);
4380  else
4381  varub = aggvar->glbdom.ub * scalar + constant;
4382  }
4383  else
4384  {
4385  if( SCIPsetIsInfinity(set, -aggvar->glbdom.lb) )
4386  varub = SCIPsetInfinity(set);
4387  else
4388  varub = aggvar->glbdom.lb * scalar + constant;
4389  if( SCIPsetIsInfinity(set, aggvar->glbdom.ub) )
4390  varlb = -SCIPsetInfinity(set);
4391  else
4392  varlb = aggvar->glbdom.ub * scalar + constant;
4393  }
4394  varlb = MAX(varlb, var->glbdom.lb);
4395  varub = MIN(varub, var->glbdom.ub);
4396  SCIPvarAdjustLb(var, set, &varlb);
4397  SCIPvarAdjustUb(var, set, &varub);
4398 
4399  /* check the new bounds */
4400  if( SCIPsetIsGT(set, varlb, varub) )
4401  {
4402  /* the aggregation is infeasible */
4403  *infeasible = TRUE;
4404  return SCIP_OKAY;
4405  }
4406  else if( SCIPsetIsEQ(set, varlb, varub) )
4407  {
4408  /* the aggregated variable is fixed -> fix both variables */
4409  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4410  eventqueue, cliquetable, varlb, infeasible, fixed) );
4411  if( !(*infeasible) )
4412  {
4413  SCIP_Bool aggfixed;
4414 
4415  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4416  eventqueue, cliquetable, (varlb-constant)/scalar, infeasible, &aggfixed) );
4417  assert(*fixed == aggfixed);
4418  }
4419  return SCIP_OKAY;
4420  }
4421  else
4422  {
4423  if( SCIPsetIsGT(set, varlb, var->glbdom.lb) )
4424  {
4425  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varlb) );
4426  }
4427  if( SCIPsetIsLT(set, varub, var->glbdom.ub) )
4428  {
4429  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, varub) );
4430  }
4431 
4432  /* update the hole list of the aggregation variable */
4433  /**@todo update hole list of aggregation variable */
4434  }
4435 
4436  /* update the bounds of the aggregation variable y in x = a*y + c -> y = (x-c)/a */
4437  if( scalar > 0.0 )
4438  {
4439  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4440  aggvarlb = -SCIPsetInfinity(set);
4441  else
4442  aggvarlb = (var->glbdom.lb - constant) / scalar;
4443  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4444  aggvarub = SCIPsetInfinity(set);
4445  else
4446  aggvarub = (var->glbdom.ub - constant) / scalar;
4447  }
4448  else
4449  {
4450  if( SCIPsetIsInfinity(set, -var->glbdom.lb) )
4451  aggvarub = SCIPsetInfinity(set);
4452  else
4453  aggvarub = (var->glbdom.lb - constant) / scalar;
4454  if( SCIPsetIsInfinity(set, var->glbdom.ub) )
4455  aggvarlb = -SCIPsetInfinity(set);
4456  else
4457  aggvarlb = (var->glbdom.ub - constant) / scalar;
4458  }
4459  aggvarlb = MAX(aggvarlb, aggvar->glbdom.lb);
4460  aggvarub = MIN(aggvarub, aggvar->glbdom.ub);
4461  SCIPvarAdjustLb(aggvar, set, &aggvarlb);
4462  SCIPvarAdjustUb(aggvar, set, &aggvarub);
4463 
4464  /* check the new bounds */
4465  if( SCIPsetIsGT(set, aggvarlb, aggvarub) )
4466  {
4467  /* the aggregation is infeasible */
4468  *infeasible = TRUE;
4469  return SCIP_OKAY;
4470  }
4471  else if( SCIPsetIsEQ(set, aggvarlb, aggvarub) )
4472  {
4473  /* the aggregation variable is fixed -> fix both variables */
4474  SCIP_CALL( SCIPvarFix(aggvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4475  eventqueue, cliquetable, aggvarlb, infeasible, fixed) );
4476  if( !(*infeasible) )
4477  {
4478  SCIP_Bool varfixed;
4479 
4480  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4481  eventqueue, cliquetable, aggvarlb * scalar + constant, infeasible, &varfixed) );
4482  assert(*fixed == varfixed);
4483  }
4484  return SCIP_OKAY;
4485  }
4486  else
4487  {
4488  SCIP_Real oldbd;
4489  if( SCIPsetIsGT(set, aggvarlb, aggvar->glbdom.lb) )
4490  {
4491  oldbd = aggvar->glbdom.lb;
4492  SCIP_CALL( SCIPvarChgLbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarlb) );
4493  aggvarbdschanged = !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.lb);
4494  }
4495  if( SCIPsetIsLT(set, aggvarub, aggvar->glbdom.ub) )
4496  {
4497  oldbd = aggvar->glbdom.ub;
4498  SCIP_CALL( SCIPvarChgUbGlobal(aggvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, aggvarub) );
4499  aggvarbdschanged = aggvarbdschanged || !SCIPsetIsEQ(set, oldbd, aggvar->glbdom.ub);
4500  }
4501 
4502  /* update the hole list of the aggregation variable */
4503  /**@todo update hole list of aggregation variable */
4504  }
4505  }
4506  while( aggvarbdschanged );
4507 
4508  SCIPsetDebugMsg(set, " new bounds: <%s> [%g,%g] <%s> [%g,%g]\n",
4509  var->name, var->glbdom.lb, var->glbdom.ub, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub);
4510 
4511  return SCIP_OKAY;
4512 }
4513 
4514 /** converts loose variable into aggregated variable */
4516  SCIP_VAR* var, /**< loose problem variable */
4517  BMS_BLKMEM* blkmem, /**< block memory */
4518  SCIP_SET* set, /**< global SCIP settings */
4519  SCIP_STAT* stat, /**< problem statistics */
4520  SCIP_PROB* transprob, /**< tranformed problem data */
4521  SCIP_PROB* origprob, /**< original problem data */
4522  SCIP_PRIMAL* primal, /**< primal data */
4523  SCIP_TREE* tree, /**< branch and bound tree */
4524  SCIP_REOPT* reopt, /**< reoptimization data structure */
4525  SCIP_LP* lp, /**< current LP data */
4526  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4527  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4528  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4529  SCIP_VAR* aggvar, /**< loose variable y in aggregation x = a*y + c */
4530  SCIP_Real scalar, /**< multiplier a in aggregation x = a*y + c */
4531  SCIP_Real constant, /**< constant shift c in aggregation x = a*y + c */
4532  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4533  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4534  )
4535 {
4536  SCIP_VAR** vars;
4537  SCIP_Real* coefs;
4538  SCIP_Real* constants;
4539  SCIP_Real obj;
4540  SCIP_Real branchfactor;
4541  SCIP_Bool fixed;
4542  int branchpriority;
4543  int nlocksdown;
4544  int nlocksup;
4545  int nvbds;
4546  int i;
4547  int j;
4548 
4549  assert(var != NULL);
4550  assert(aggvar != NULL);
4551  assert(var->scip == set->scip);
4552  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
4553  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
4554  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE);
4555  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
4556  assert(infeasible != NULL);
4557  assert(aggregated != NULL);
4558 
4559  *infeasible = FALSE;
4560  *aggregated = FALSE;
4561 
4562  /* get active problem variable of aggregation variable */
4563  SCIP_CALL( SCIPvarGetProbvarSum(&aggvar, set, &scalar, &constant) );
4564 
4565  /* aggregation is a fixing, if the scalar is zero */
4566  if( SCIPsetIsZero(set, scalar) )
4567  {
4568  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand, eventqueue,
4569  cliquetable, constant, infeasible, aggregated) );
4570  return SCIP_OKAY;
4571  }
4572 
4573  /* don't perform the aggregation if the aggregation variable is multi-aggregated itself */
4574  if( SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_MULTAGGR )
4575  return SCIP_OKAY;
4576 
4577  /**@todo currently we don't perform the aggregation if the aggregation variable has a non-empty hole list; this
4578  * should be changed in the future
4579  */
4580  if( SCIPvarGetHolelistGlobal(var) != NULL )
4581  return SCIP_OKAY;
4582 
4583  assert(aggvar->glbdom.lb == aggvar->locdom.lb); /*lint !e777*/
4584  assert(aggvar->glbdom.ub == aggvar->locdom.ub); /*lint !e777*/
4585  assert(SCIPvarGetStatus(aggvar) == SCIP_VARSTATUS_LOOSE);
4586 
4587  SCIPsetDebugMsg(set, "aggregate variable <%s>[%g,%g] == %g*<%s>[%g,%g] %+g\n", var->name, var->glbdom.lb, var->glbdom.ub,
4588  scalar, aggvar->name, aggvar->glbdom.lb, aggvar->glbdom.ub, constant);
4589 
4590  /* if variable and aggregation variable are equal, the variable can be fixed: x == a*x + c => x == c/(1-a) */
4591  if( var == aggvar )
4592  {
4593  if( SCIPsetIsEQ(set, scalar, 1.0) )
4594  *infeasible = !SCIPsetIsZero(set, constant);
4595  else
4596  {
4597  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
4598  eventqueue, cliquetable, constant/(1.0-scalar), infeasible, aggregated) );
4599  }
4600  return SCIP_OKAY;
4601  }
4602 
4603  /* tighten the bounds of aggregated and aggregation variable */
4604  SCIP_CALL( varUpdateAggregationBounds(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
4605  branchcand, eventqueue, cliquetable, aggvar, scalar, constant, infeasible, &fixed) );
4606  if( *infeasible || fixed )
4607  {
4608  *aggregated = fixed;
4609  return SCIP_OKAY;
4610  }
4611 
4612  /* delete implications and variable bounds of the aggregated variable from other variables, but keep them in the
4613  * aggregated variable
4614  */
4615  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, FALSE) );
4616  assert(var->cliquelist == NULL);
4617 
4618  /* set the aggregated variable's objective value to 0.0 */
4619  obj = var->obj;
4620  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
4621 
4622  /* unlock all rounding locks */
4623  nlocksdown = var->nlocksdown;
4624  nlocksup = var->nlocksup;
4625  var->nlocksdown = 0;
4626  var->nlocksup = 0;
4627 
4628  /* check, if variable should be used as NEGATED variable of the aggregation variable */
4629  if( SCIPvarIsBinary(var) && SCIPvarIsBinary(aggvar)
4630  && var->negatedvar == NULL && aggvar->negatedvar == NULL
4631  && SCIPsetIsEQ(set, scalar, -1.0) && SCIPsetIsEQ(set, constant, 1.0) )
4632  {
4633  /* link both variables as negation pair */
4634  var->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
4635  var->data.negate.constant = 1.0;
4636  var->negatedvar = aggvar;
4637  aggvar->negatedvar = var;
4638 
4639  /* copy doNotMultiaggr status */
4640  aggvar->donotmultaggr |= var->donotmultaggr;
4641 
4642  /* mark both variables to be non-deletable */
4644  SCIPvarMarkNotDeletable(aggvar);
4645  }
4646  else
4647  {
4648  /* convert variable into aggregated variable */
4649  var->varstatus = SCIP_VARSTATUS_AGGREGATED; /*lint !e641*/
4650  var->data.aggregate.var = aggvar;
4651  var->data.aggregate.scalar = scalar;
4652  var->data.aggregate.constant = constant;
4653 
4654  /* copy doNotMultiaggr status */
4655  aggvar->donotmultaggr |= var->donotmultaggr;
4656 
4657  /* mark both variables to be non-deletable */
4659  SCIPvarMarkNotDeletable(aggvar);
4660  }
4661 
4662  /* make aggregated variable a parent of the aggregation variable */
4663  SCIP_CALL( varAddParent(aggvar, blkmem, set, var) );
4664 
4665  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variable */
4666  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
4667 
4668  /* move the variable bounds to the aggregation variable:
4669  * - add all variable bounds again to the variable, thus adding it to the aggregation variable
4670  * - free the variable bounds data structures
4671  */
4672  if( var->vlbs != NULL )
4673  {
4674  nvbds = SCIPvboundsGetNVbds(var->vlbs);
4675  vars = SCIPvboundsGetVars(var->vlbs);
4676  coefs = SCIPvboundsGetCoefs(var->vlbs);
4677  constants = SCIPvboundsGetConstants(var->vlbs);
4678  for( i = 0; i < nvbds && !(*infeasible); ++i )
4679  {
4680  SCIP_CALL( SCIPvarAddVlb(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4681  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4682  }
4683  }
4684  if( var->vubs != NULL )
4685  {
4686  nvbds = SCIPvboundsGetNVbds(var->vubs);
4687  vars = SCIPvboundsGetVars(var->vubs);
4688  coefs = SCIPvboundsGetCoefs(var->vubs);
4689  constants = SCIPvboundsGetConstants(var->vubs);
4690  for( i = 0; i < nvbds && !(*infeasible); ++i )
4691  {
4692  SCIP_CALL( SCIPvarAddVub(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
4693  eventqueue, vars[i], coefs[i], constants[i], FALSE, infeasible, NULL) );
4694  }
4695  }
4696  SCIPvboundsFree(&var->vlbs, blkmem);
4697  SCIPvboundsFree(&var->vubs, blkmem);
4698 
4699  /* move the implications to the aggregation variable:
4700  * - add all implications again to the variable, thus adding it to the aggregation variable
4701  * - free the implications data structures
4702  */
4703  if( var->implics != NULL && SCIPvarGetType(aggvar) == SCIP_VARTYPE_BINARY )
4704  {
4705  assert(SCIPvarIsBinary(var));
4706  for( i = 0; i < 2; ++i )
4707  {
4708  SCIP_VAR** implvars;
4709  SCIP_BOUNDTYPE* impltypes;
4710  SCIP_Real* implbounds;
4711  int nimpls;
4712 
4713  nimpls = SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i);
4714  implvars = SCIPimplicsGetVars(var->implics, (SCIP_Bool)i);
4715  impltypes = SCIPimplicsGetTypes(var->implics, (SCIP_Bool)i);
4716  implbounds = SCIPimplicsGetBounds(var->implics, (SCIP_Bool)i);
4717 
4718  for( j = 0; j < nimpls && !(*infeasible); ++j )
4719  {
4720  /* @todo can't we omit transitive closure, because it should already have been done when adding the
4721  * implication to the aggregated variable?
4722  */
4723  SCIP_CALL( SCIPvarAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
4724  branchcand, eventqueue, (SCIP_Bool)i, implvars[j], impltypes[j], implbounds[j], FALSE, infeasible,
4725  NULL) );
4726  assert(nimpls == SCIPimplicsGetNImpls(var->implics, (SCIP_Bool)i));
4727  }
4728  }
4729  }
4730  SCIPimplicsFree(&var->implics, blkmem);
4731 
4732  /* add the history entries to the aggregation variable and clear the history of the aggregated variable */
4733  SCIPhistoryUnite(aggvar->history, var->history, scalar < 0.0);
4734  SCIPhistoryUnite(aggvar->historycrun, var->historycrun, scalar < 0.0);
4735  SCIPhistoryReset(var->history);
4737 
4738  /* update flags of aggregation variable */
4739  aggvar->removable &= var->removable;
4740 
4741  /* update branching factors and priorities of both variables to be the maximum of both variables */
4742  branchfactor = MAX(aggvar->branchfactor, var->branchfactor);
4743  branchpriority = MAX(aggvar->branchpriority, var->branchpriority);
4744  SCIP_CALL( SCIPvarChgBranchFactor(aggvar, set, branchfactor) );
4745  SCIP_CALL( SCIPvarChgBranchPriority(aggvar, branchpriority) );
4746  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
4747  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
4748 
4749  /* update branching direction of both variables to agree to a single direction */
4750  if( scalar >= 0.0 )
4751  {
4753  {
4755  }
4756  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4757  {
4759  }
4760  else if( var->branchdirection != aggvar->branchdirection )
4761  {
4763  }
4764  }
4765  else
4766  {
4768  {
4770  }
4771  else if( (SCIP_BRANCHDIR)aggvar->branchdirection == SCIP_BRANCHDIR_AUTO )
4772  {
4774  }
4775  else if( var->branchdirection != aggvar->branchdirection )
4776  {
4778  }
4779  }
4780 
4781  if( var->probindex != -1 )
4782  {
4783  /* inform problem about the variable's status change */
4784  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
4785  }
4786 
4787  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
4788  * variable and the problem's objective offset
4789  */
4790  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
4791 
4792  /* issue VARFIXED event */
4793  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 1) );
4794 
4795  *aggregated = TRUE;
4796 
4797  return SCIP_OKAY;
4798 }
4799 
4800 /** Tries to aggregate an equality a*x + b*y == c consisting of two (implicit) integral active problem variables x and
4801  * y. An integer aggregation (i.e. integral coefficients a' and b', such that a'*x + b'*y == c') is searched.
4802  *
4803  * This can lead to the detection of infeasibility (e.g. if c' is fractional), or to a rejection of the aggregation
4804  * (denoted by aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
4805  */
4806 static
4808  SCIP_SET* set, /**< global SCIP settings */
4809  BMS_BLKMEM* blkmem, /**< block memory */
4810  SCIP_STAT* stat, /**< problem statistics */
4811  SCIP_PROB* transprob, /**< tranformed problem data */
4812  SCIP_PROB* origprob, /**< original problem data */
4813  SCIP_PRIMAL* primal, /**< primal data */
4814  SCIP_TREE* tree, /**< branch and bound tree */
4815  SCIP_REOPT* reopt, /**< reoptimization data structure */
4816  SCIP_LP* lp, /**< current LP data */
4817  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
4818  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
4819  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
4820  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
4821  SCIP_VAR* varx, /**< integral variable x in equality a*x + b*y == c */
4822  SCIP_VAR* vary, /**< integral variable y in equality a*x + b*y == c */
4823  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
4824  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
4825  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
4826  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
4827  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
4828  )
4829 {
4830  SCIP_VAR* aggvar;
4831  char aggvarname[SCIP_MAXSTRLEN];
4832  SCIP_Longint scalarxn = 0;
4833  SCIP_Longint scalarxd = 0;
4834  SCIP_Longint scalaryn = 0;
4835  SCIP_Longint scalaryd = 0;
4836  SCIP_Longint a;
4837  SCIP_Longint b;
4838  SCIP_Longint c;
4839  SCIP_Longint scm;
4840  SCIP_Longint gcd;
4841  SCIP_Longint currentclass;
4842  SCIP_Longint classstep;
4843  SCIP_Longint xsol;
4844  SCIP_Longint ysol;
4845  SCIP_Bool success;
4846  SCIP_VARTYPE vartype;
4847 
4848 #define MAXDNOM 1000000LL
4849 
4850  assert(set != NULL);
4851  assert(blkmem != NULL);
4852  assert(stat != NULL);
4853  assert(transprob != NULL);
4854  assert(origprob != NULL);
4855  assert(tree != NULL);
4856  assert(lp != NULL);
4857  assert(cliquetable != NULL);
4858  assert(branchcand != NULL);
4859  assert(eventqueue != NULL);
4860  assert(varx != NULL);
4861  assert(vary != NULL);
4862  assert(varx != vary);
4863  assert(infeasible != NULL);
4864  assert(aggregated != NULL);
4865  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
4866  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
4868  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
4870  assert(!SCIPsetIsZero(set, scalarx));
4871  assert(!SCIPsetIsZero(set, scalary));
4872 
4873  *infeasible = FALSE;
4874  *aggregated = FALSE;
4875 
4876  /* get rational representation of coefficients */
4877  success = SCIPrealToRational(scalarx, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalarxn, &scalarxd);
4878  if( success )
4879  success = SCIPrealToRational(scalary, -SCIPsetEpsilon(set), SCIPsetEpsilon(set), MAXDNOM, &scalaryn, &scalaryd);
4880  if( !success )
4881  return SCIP_OKAY;
4882  assert(scalarxd >= 1);
4883  assert(scalaryd >= 1);
4884 
4885  /* multiply equality with smallest common denominator */
4886  scm = SCIPcalcSmaComMul(scalarxd, scalaryd);
4887  a = (scm/scalarxd)*scalarxn;
4888  b = (scm/scalaryd)*scalaryn;
4889  rhs *= scm;
4890 
4891  /* divide equality by the greatest common divisor of a and b */
4892  gcd = SCIPcalcGreComDiv(ABS(a), ABS(b));
4893  a /= gcd;
4894  b /= gcd;
4895  rhs /= gcd;
4896  assert(a != 0);
4897  assert(b != 0);
4898 
4899  /* check, if right hand side is integral */
4900  if( !SCIPsetIsFeasIntegral(set, rhs) )
4901  {
4902  *infeasible = TRUE;
4903  return SCIP_OKAY;
4904  }
4905  c = (SCIP_Longint)(SCIPsetFeasFloor(set, rhs));
4906 
4907  if( REALABS((SCIP_Real)(c/a)) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
4908  return SCIP_OKAY;
4909 
4910  /* check, if we are in an easy case with either |a| = 1 or |b| = 1 */
4911  if( (a == 1 || a == -1) && SCIPvarGetType(vary) == SCIP_VARTYPE_INTEGER )
4912  {
4913  /* aggregate x = - b/a*y + c/a */
4914  /*lint --e{653}*/
4915  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4916  branchcand, eventqueue, vary, (SCIP_Real)(-b/a), (SCIP_Real)(c/a), infeasible, aggregated) );
4917  assert(*aggregated);
4918  return SCIP_OKAY;
4919  }
4920  if( (b == 1 || b == -1) && SCIPvarGetType(varx) == SCIP_VARTYPE_INTEGER )
4921  {
4922  /* aggregate y = - a/b*x + c/b */
4923  /*lint --e{653}*/
4924  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
4925  branchcand, eventqueue, varx, (SCIP_Real)(-a/b), (SCIP_Real)(c/b), infeasible, aggregated) );
4926  assert(*aggregated);
4927  return SCIP_OKAY;
4928  }
4929 
4930  /* Both variables are integers, their coefficients are not multiples of each other, and they don't have any
4931  * common divisor. Let (x',y') be a solution of the equality
4932  * a*x + b*y == c -> a*x == c - b*y
4933  * Then x = -b*z + x', y = a*z + y' with z integral gives all solutions to the equality.
4934  */
4935 
4936  /* find initial solution (x',y'):
4937  * - find y' such that c - b*y' is a multiple of a
4938  * - start in equivalence class c%a
4939  * - step through classes, where each step increases class number by (-b)%a, until class 0 is visited
4940  * - if equivalence class 0 is visited, we are done: y' equals the number of steps taken
4941  * - 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
4942  * - calculate x' with x' = (c - b*y')/a (which must be integral)
4943  *
4944  * Algorithm works for a > 0 only.
4945  */
4946  if( a < 0 )
4947  {
4948  a = -a;
4949  b = -b;
4950  c = -c;
4951  }
4952  assert(0 <= a);
4953 
4954  /* search upwards from ysol = 0 */
4955  ysol = 0;
4956  currentclass = c%a;
4957  if( currentclass < 0 )
4958  currentclass += a;
4959  assert(0 <= currentclass && currentclass < a);
4960 
4961  classstep = (-b)%a;
4962 
4963  if( classstep < 0 )
4964  classstep += a;
4965  assert(0 <= classstep && classstep < a);
4966 
4967  while( currentclass != 0 )
4968  {
4969  assert(0 <= currentclass && currentclass < a);
4970  currentclass += classstep;
4971  if( currentclass >= a )
4972  currentclass -= a;
4973  ysol++;
4974  }
4975  assert(ysol < a);
4976  assert(((c - b*ysol)%a) == 0);
4977 
4978  xsol = (c - b*ysol)/a;
4979 
4980  /* determine variable type for new artificial variable:
4981  *
4982  * if both variables are implicit integer the new variable can be implicit too, because the integer implication on
4983  * these both variables should be enforced by some other variables, otherwise the new variable needs to be of
4984  * integral type
4985  */
4988 
4989  /* feasible solutions are (x,y) = (x',y') + z*(-b,a)
4990  * - create new integer variable z with infinite bounds
4991  * - aggregate variable x = -b*z + x'
4992  * - aggregate variable y = a*z + y'
4993  * - the bounds of z are calculated automatically during aggregation
4994  */
4995  (void) SCIPsnprintf(aggvarname, SCIP_MAXSTRLEN, "agg%d", stat->nvaridx);
4996  SCIP_CALL( SCIPvarCreateTransformed(&aggvar, blkmem, set, stat,
4997  aggvarname, -SCIPsetInfinity(set), SCIPsetInfinity(set), 0.0, vartype,
4999  NULL, NULL, NULL, NULL, NULL) );
5000 
5001  SCIP_CALL( SCIPprobAddVar(transprob, blkmem, set, lp, branchcand, eventfilter, eventqueue, aggvar) );
5002 
5003  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5004  branchcand, eventqueue, aggvar, (SCIP_Real)(-b), (SCIP_Real)xsol, infeasible, aggregated) );
5005  assert(*aggregated || *infeasible);
5006 
5007  if( !(*infeasible) )
5008  {
5009  SCIP_CALL( SCIPvarAggregate(vary, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5010  branchcand, eventqueue, aggvar, (SCIP_Real)a, (SCIP_Real)ysol, infeasible, aggregated) );
5011  assert(*aggregated || *infeasible);
5012  }
5013 
5014  /* release z */
5015  SCIP_CALL( SCIPvarRelease(&aggvar, blkmem, set, eventqueue, lp) );
5016 
5017  return SCIP_OKAY;
5018 }
5019 
5020 /** performs second step of SCIPaggregateVars():
5021  * the variable to be aggregated is chosen among active problem variables x' and y', preferring a less strict variable
5022  * type as aggregation variable (i.e. continuous variables are preferred over implicit integers, implicit integers
5023  * or integers over binaries). If none of the variables is continuous, it is tried to find an integer
5024  * aggregation (i.e. integral coefficients a'' and b'', such that a''*x' + b''*y' == c''). This can lead to
5025  * the detection of infeasibility (e.g. if c'' is fractional), or to a rejection of the aggregation (denoted by
5026  * aggregated == FALSE), if the resulting integer coefficients are too large and thus numerically instable.
5027  *
5028  * @todo check for fixings, infeasibility, bound changes, or domain holes:
5029  * a) if there is no easy aggregation and we have one binary variable and another integer/implicit/binary variable
5030  * b) for implicit integer variables with fractional aggregation scalar (we cannot (for technical reasons) and do
5031  * not want to aggregate implicit integer variables, since we loose the corresponding divisibility property)
5032  */
5034  SCIP_SET* set, /**< global SCIP settings */
5035  BMS_BLKMEM* blkmem, /**< block memory */
5036  SCIP_STAT* stat, /**< problem statistics */
5037  SCIP_PROB* transprob, /**< tranformed problem data */
5038  SCIP_PROB* origprob, /**< original problem data */
5039  SCIP_PRIMAL* primal, /**< primal data */
5040  SCIP_TREE* tree, /**< branch and bound tree */
5041  SCIP_REOPT* reopt, /**< reoptimization data structure */
5042  SCIP_LP* lp, /**< current LP data */
5043  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5044  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5045  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5046  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5047  SCIP_VAR* varx, /**< variable x in equality a*x + b*y == c */
5048  SCIP_VAR* vary, /**< variable y in equality a*x + b*y == c */
5049  SCIP_Real scalarx, /**< multiplier a in equality a*x + b*y == c */
5050  SCIP_Real scalary, /**< multiplier b in equality a*x + b*y == c */
5051  SCIP_Real rhs, /**< right hand side c in equality a*x + b*y == c */
5052  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5053  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5054  )
5055 {
5056  SCIP_Bool easyaggr;
5057  SCIP_Real maxscalar;
5058  SCIP_Real absquot;
5059 
5060  assert(set != NULL);
5061  assert(blkmem != NULL);
5062  assert(stat != NULL);
5063  assert(transprob != NULL);
5064  assert(origprob != NULL);
5065  assert(tree != NULL);
5066  assert(lp != NULL);
5067  assert(cliquetable != NULL);
5068  assert(branchcand != NULL);
5069  assert(eventqueue != NULL);
5070  assert(varx != NULL);
5071  assert(vary != NULL);
5072  assert(varx != vary);
5073  assert(infeasible != NULL);
5074  assert(aggregated != NULL);
5075  assert(SCIPsetGetStage(set) == SCIP_STAGE_PRESOLVING);
5076  assert(SCIPvarGetStatus(varx) == SCIP_VARSTATUS_LOOSE);
5077  assert(SCIPvarGetStatus(vary) == SCIP_VARSTATUS_LOOSE);
5078  assert(!SCIPsetIsZero(set, scalarx));
5079  assert(!SCIPsetIsZero(set, scalary));
5080 
5081  *infeasible = FALSE;
5082  *aggregated = FALSE;
5083 
5084  absquot = REALABS(scalarx / scalary);
5085  maxscalar = SCIPsetFeastol(set) / SCIPsetEpsilon(set);
5086  maxscalar = MAX(maxscalar, 1.0);
5087 
5088  if( absquot > maxscalar || absquot < 1 / maxscalar )
5089  return SCIP_OKAY;
5090 
5091  /* prefer aggregating the variable of more general type (preferred aggregation variable is varx) */
5092  if( SCIPvarGetType(vary) > SCIPvarGetType(varx) ||
5093  (SCIPvarGetType(vary) == SCIPvarGetType(varx) && !SCIPvarIsBinary(vary) && SCIPvarIsBinary(varx)) )
5094  {
5095  SCIP_VAR* var;
5096  SCIP_Real scalar;
5097 
5098  /* switch the variables, such that varx is the variable of more general type (cont > implint > int > bin) */
5099  var = vary;
5100  vary = varx;
5101  varx = var;
5102  scalar = scalary;
5103  scalary = scalarx;
5104  scalarx = scalar;
5105  }
5106 
5107  /* don't aggregate if the aggregation would lead to a binary variable aggregated to a non-binary variable */
5108  if( SCIPvarIsBinary(varx) && !SCIPvarIsBinary(vary) )
5109  return SCIP_OKAY;
5110 
5111  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5112 
5113  /* figure out, which variable should be aggregated */
5114  easyaggr = FALSE;
5115 
5116  /* check if it is an easy aggregation that means:
5117  *
5118  * a*x + b*y == c -> x == -b/a * y + c/a iff |b/a| > feastol and |a/b| > feastol
5119  */
5120  if( !SCIPsetIsFeasZero(set, scalary/scalarx) && !SCIPsetIsFeasZero(set, scalarx/scalary) )
5121  {
5123  {
5124  easyaggr = TRUE;
5125  }
5126  else if( SCIPsetIsFeasIntegral(set, scalary/scalarx) )
5127  {
5128  easyaggr = TRUE;
5129  }
5130  else if( SCIPsetIsFeasIntegral(set, scalarx/scalary) && SCIPvarGetType(vary) == SCIPvarGetType(varx) )
5131  {
5132  /* we have an easy aggregation if we flip the variables x and y */
5133  SCIP_VAR* var;
5134  SCIP_Real scalar;
5135 
5136  /* switch the variables, such that varx is the aggregated variable */
5137  var = vary;
5138  vary = varx;
5139  varx = var;
5140  scalar = scalary;
5141  scalary = scalarx;
5142  scalarx = scalar;
5143  easyaggr = TRUE;
5144  }
5145  else if( SCIPvarGetType(varx) == SCIP_VARTYPE_CONTINUOUS )
5146  {
5147  /* the aggregation is still easy if both variables are continuous */
5148  assert(SCIPvarGetType(vary) == SCIP_VARTYPE_CONTINUOUS); /* otherwise we are in the first case */
5149  easyaggr = TRUE;
5150  }
5151  }
5152 
5153  /* did we find an "easy" aggregation? */
5154  if( easyaggr )
5155  {
5156  SCIP_Real scalar;
5157  SCIP_Real constant;
5158 
5159  assert(SCIPvarGetType(varx) >= SCIPvarGetType(vary));
5160 
5161  /* calculate aggregation scalar and constant: a*x + b*y == c => x == -b/a * y + c/a */
5162  scalar = -scalary/scalarx;
5163  constant = rhs/scalarx;
5164 
5165  if( REALABS(constant) > SCIPsetGetHugeValue(set) * SCIPsetFeastol(set) ) /*lint !e653*/
5166  return SCIP_OKAY;
5167 
5168  /* check aggregation for integer feasibility */
5171  && SCIPsetIsFeasIntegral(set, scalar) && !SCIPsetIsFeasIntegral(set, constant) )
5172  {
5173  *infeasible = TRUE;
5174  return SCIP_OKAY;
5175  }
5176 
5177  /* if the aggregation scalar is fractional, we cannot (for technical reasons) and do not want to aggregate implicit integer variables,
5178  * since then we would loose the corresponding divisibility property
5179  */
5180  assert(SCIPvarGetType(varx) != SCIP_VARTYPE_IMPLINT || SCIPsetIsFeasIntegral(set, scalar));
5181 
5182  /* aggregate the variable */
5183  SCIP_CALL( SCIPvarAggregate(varx, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5184  branchcand, eventqueue, vary, scalar, constant, infeasible, aggregated) );
5185  assert(*aggregated || *infeasible);
5186  }
5189  {
5190  /* the variables are both integral: we have to try to find an integer aggregation */
5191  SCIP_CALL( tryAggregateIntVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp, cliquetable,
5192  branchcand, eventfilter, eventqueue, varx, vary, scalarx, scalary, rhs, infeasible, aggregated) );
5193  }
5194 
5195  return SCIP_OKAY;
5196 }
5197 
5198 /** converts variable into multi-aggregated variable */
5200  SCIP_VAR* var, /**< problem variable */
5201  BMS_BLKMEM* blkmem, /**< block memory */
5202  SCIP_SET* set, /**< global SCIP settings */
5203  SCIP_STAT* stat, /**< problem statistics */
5204  SCIP_PROB* transprob, /**< tranformed problem data */
5205  SCIP_PROB* origprob, /**< original problem data */
5206  SCIP_PRIMAL* primal, /**< primal data */
5207  SCIP_TREE* tree, /**< branch and bound tree */
5208  SCIP_REOPT* reopt, /**< reoptimization data structure */
5209  SCIP_LP* lp, /**< current LP data */
5210  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5211  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
5212  SCIP_EVENTFILTER* eventfilter, /**< event filter for global (not variable dependent) events */
5213  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5214  int naggvars, /**< number n of variables in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5215  SCIP_VAR** aggvars, /**< variables y_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5216  SCIP_Real* scalars, /**< multipliers a_i in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5217  SCIP_Real constant, /**< constant shift c in aggregation x = a_1*y_1 + ... + a_n*y_n + c */
5218  SCIP_Bool* infeasible, /**< pointer to store whether the aggregation is infeasible */
5219  SCIP_Bool* aggregated /**< pointer to store whether the aggregation was successful */
5220  )
5221 {
5222  SCIP_VAR** tmpvars;
5223  SCIP_Real* tmpscalars;
5224  SCIP_Real obj;
5225  SCIP_Real branchfactor;
5226  int branchpriority;
5227  SCIP_BRANCHDIR branchdirection;
5228  int nlocksdown;
5229  int nlocksup;
5230  int v;
5231  SCIP_Real tmpconstant;
5232  SCIP_Real tmpscalar;
5233  int ntmpvars;
5234  int tmpvarssize;
5235  int tmprequiredsize;
5236 
5237  assert(var != NULL);
5238  assert(var->scip == set->scip);
5239  assert(var->glbdom.lb == var->locdom.lb); /*lint !e777*/
5240  assert(var->glbdom.ub == var->locdom.ub); /*lint !e777*/
5241  assert(naggvars == 0 || aggvars != NULL);
5242  assert(naggvars == 0 || scalars != NULL);
5243  assert(infeasible != NULL);
5244  assert(aggregated != NULL);
5245 
5246  SCIPsetDebugMsg(set, "trying multi-aggregating variable <%s> == ...%d vars... %+g\n", var->name, naggvars, constant);
5247 
5248  *infeasible = FALSE;
5249  *aggregated = FALSE;
5250 
5251  switch( SCIPvarGetStatus(var) )
5252  {
5254  if( var->data.original.transvar == NULL )
5255  {
5256  SCIPerrorMessage("cannot multi-aggregate an untransformed original variable\n");
5257  return SCIP_INVALIDDATA;
5258  }
5259  SCIP_CALL( SCIPvarMultiaggregate(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
5260  reopt, lp, cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars, constant, infeasible, aggregated) );
5261  break;
5262 
5263  case SCIP_VARSTATUS_LOOSE:
5264  assert(!SCIPeventqueueIsDelayed(eventqueue)); /* otherwise, the pseudo objective value update gets confused */
5265 
5266  /* check if we would create a self-reference */
5267  ntmpvars = naggvars;
5268  tmpvarssize = naggvars;
5269  tmpconstant = constant;
5270  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpvars, aggvars, ntmpvars) );
5271  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &tmpscalars, scalars, ntmpvars) );
5272 
5273  /* get all active variables for multi-aggregation */
5274  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5275  if( tmprequiredsize > tmpvarssize )
5276  {
5277  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpvars, tmpvarssize, tmprequiredsize) );
5278  SCIP_ALLOC( BMSreallocBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize, tmprequiredsize) );
5279  tmpvarssize = tmprequiredsize;
5280  SCIP_CALL( SCIPvarGetActiveRepresentatives(set, tmpvars, tmpscalars, &ntmpvars, tmpvarssize, &tmpconstant, &tmprequiredsize, FALSE) );
5281  assert( tmprequiredsize <= tmpvarssize );
5282  }
5283 
5284  tmpscalar = 0.0;
5285 
5286  /* iterate over all active variables of the multi-aggregation and filter all variables which are equal to the
5287  * possible multi-aggregated variable
5288  */
5289  for( v = ntmpvars - 1; v >= 0; --v )
5290  {
5291  assert(tmpvars[v] != NULL);
5292  assert(SCIPvarGetStatus(tmpvars[v]) == SCIP_VARSTATUS_LOOSE);
5293 
5294  if( tmpvars[v]->index == var->index )
5295  {
5296  tmpscalar += tmpscalars[v];
5297  tmpvars[v] = tmpvars[ntmpvars - 1];
5298  tmpscalars[v] = tmpscalars[ntmpvars - 1];
5299  --ntmpvars;
5300  }
5301  }
5302 
5303  /* this means that x = x + a_1*y_1 + ... + a_n*y_n + c */
5304  if( SCIPsetIsEQ(set, tmpscalar, 1.0) )
5305  {
5306  if( ntmpvars == 0 )
5307  {
5308  if( SCIPsetIsZero(set, tmpconstant) ) /* x = x */
5309  {
5310  SCIPsetDebugMsg(set, "Possible multi-aggregation was completely resolved and detected to be redundant.\n");
5311  goto TERMINATE;
5312  }
5313  else /* 0 = c and c != 0 */
5314  {
5315  SCIPsetDebugMsg(set, "Multi-aggregation was completely resolved and led to infeasibility.\n");
5316  *infeasible = TRUE;
5317  goto TERMINATE;
5318  }
5319  }
5320  else if( ntmpvars == 1 ) /* 0 = a*y + c => y = -c/a */
5321  {
5322  assert(tmpscalars[0] != 0.0);
5323  assert(tmpvars[0] != NULL);
5324 
5325  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(tmpvars[0]), -constant/tmpscalars[0]);
5326  SCIP_CALL( SCIPvarFix(tmpvars[0], blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5327  branchcand, eventqueue, cliquetable, -constant/tmpscalars[0], infeasible, aggregated) );
5328  goto TERMINATE;
5329  }
5330  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 */
5331  {
5332  /* both variables are different active problem variables, and both scalars are non-zero: try to aggregate them */
5333 
5334  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5335  SCIPvarGetName(tmpvars[0]), SCIPvarGetName(tmpvars[1]), tmpscalars[0], tmpscalars[1], -tmpconstant);
5336 
5337  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5338  cliquetable, branchcand, eventfilter, eventqueue, tmpvars[0], tmpvars[1], tmpscalars[0],
5339  tmpscalars[1], -tmpconstant, infeasible, aggregated) );
5340 
5341  goto TERMINATE;
5342  }
5343  else
5344  /* @todo: it is possible to multi-aggregate another variable, does it make sense?,
5345  * rest looks like 0 = a_1*y_1 + ... + a_n*y_n + c and has at least three variables
5346  */
5347  goto TERMINATE;
5348  }
5349  /* this means that x = b*x + a_1*y_1 + ... + a_n*y_n + c */
5350  else if( !SCIPsetIsZero(set, tmpscalar) )
5351  {
5352  tmpscalar = 1 - tmpscalar;
5353  tmpconstant /= tmpscalar;
5354  for( v = ntmpvars - 1; v >= 0; --v )
5355  tmpscalars[v] /= tmpscalar;
5356  }
5357 
5358  /* check, if we are in one of the simple cases */
5359  if( ntmpvars == 0 )
5360  {
5361  SCIPsetDebugMsg(set, "Possible multi-aggregation led to fixing of variable <%s> to %g.\n", SCIPvarGetName(var), tmpconstant);
5362  SCIP_CALL( SCIPvarFix(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, branchcand,
5363  eventqueue, cliquetable, tmpconstant, infeasible, aggregated) );
5364  goto TERMINATE;
5365  }
5366 
5367  /* if only one aggregation variable is left, we perform a normal aggregation instead of a multi-aggregation */
5368  if( ntmpvars == 1 )
5369  {
5370  SCIPsetDebugMsg(set, "Possible multi-aggregation led to aggregation of variables <%s> and <%s> with scalars %g and %g and constant %g.\n",
5371  SCIPvarGetName(var), SCIPvarGetName(tmpvars[0]), 1.0, -tmpscalars[0], tmpconstant);
5372 
5373  SCIP_CALL( SCIPvarTryAggregateVars(set, blkmem, stat, transprob, origprob, primal, tree, reopt, lp,
5374  cliquetable, branchcand, eventfilter, eventqueue, var, tmpvars[0], 1.0, -tmpscalars[0], tmpconstant,
5375  infeasible, aggregated) );
5376 
5377  goto TERMINATE;
5378  }
5379 
5380  /**@todo currently we don't perform the multi aggregation if the multi aggregation variable has a non
5381  * empty hole list; this should be changed in the future */
5382  if( SCIPvarGetHolelistGlobal(var) != NULL )
5383  goto TERMINATE;
5384 
5385  /* if the variable is not allowed to be multi-aggregated */
5386  if( SCIPvarDoNotMultaggr(var) )
5387  {
5388  SCIPsetDebugMsg(set, "variable is not allowed to be multi-aggregated.\n");
5389  goto TERMINATE;
5390  }
5391 
5392  /* if the variable to be multi-aggregated has implications or variable bounds (i.e. is the implied variable or
5393  * variable bound variable of another variable), we have to remove it from the other variables implications or
5394  * variable bounds
5395  */
5396  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5397  assert(var->vlbs == NULL);
5398  assert(var->vubs == NULL);
5399  assert(var->implics == NULL);
5400  assert(var->cliquelist == NULL);
5401 
5402  /* set the aggregated variable's objective value to 0.0 */
5403  obj = var->obj;
5404  SCIP_CALL( SCIPvarChgObj(var, blkmem, set, transprob, primal, lp, eventqueue, 0.0) );
5405 
5406  /* since we change the variable type form loose to multi aggregated, we have to adjust the number of loose
5407  * variables in the LP data structure; the loose objective value (looseobjval) in the LP data structure, however,
5408  * gets adjusted automatically, due to the event SCIP_EVENTTYPE_OBJCHANGED which dropped in the moment where the
5409  * objective of this variable is set to zero
5410  */
5411  SCIPlpDecNLoosevars(lp);
5412 
5413  /* unlock all rounding locks */
5414  nlocksdown = var->nlocksdown;
5415  nlocksup = var->nlocksup;
5416  var->nlocksdown = 0;
5417  var->nlocksup = 0;
5418 
5419  /* convert variable into multi-aggregated variable */
5420  var->varstatus = SCIP_VARSTATUS_MULTAGGR; /*lint !e641*/
5421  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.vars, tmpvars, ntmpvars) );
5422  SCIP_ALLOC( BMSduplicateBlockMemoryArray(blkmem, &var->data.multaggr.scalars, tmpscalars, ntmpvars) );
5423  var->data.multaggr.constant = tmpconstant;
5424  var->data.multaggr.nvars = ntmpvars;
5425  var->data.multaggr.varssize = ntmpvars;
5426 
5427  /* mark variable to be non-deletable */
5429 
5430  /* relock the rounding locks of the variable, thus increasing the locks of the aggregation variables */
5431  SCIP_CALL( SCIPvarAddLocks(var, blkmem, set, eventqueue, nlocksdown, nlocksup) );
5432 
5433  /* update flags and branching factors and priorities of aggregation variables;
5434  * update preferred branching direction of all aggregation variables that don't have a preferred direction yet
5435  */
5436  branchfactor = var->branchfactor;
5437  branchpriority = var->branchpriority;
5438  branchdirection = (SCIP_BRANCHDIR)var->branchdirection;
5439 
5440  for( v = 0; v < ntmpvars; ++v )
5441  {
5442  assert(tmpvars[v] != NULL);
5443  tmpvars[v]->removable &= var->removable;
5444  branchfactor = MAX(tmpvars[v]->branchfactor, branchfactor);
5445  branchpriority = MAX(tmpvars[v]->branchpriority, branchpriority);
5446 
5447  /* mark variable to be non-deletable */
5448  SCIPvarMarkNotDeletable(tmpvars[v]);
5449  }
5450  for( v = 0; v < ntmpvars; ++v )
5451  {
5452  SCIP_CALL( SCIPvarChgBranchFactor(tmpvars[v], set, branchfactor) );
5453  SCIP_CALL( SCIPvarChgBranchPriority(tmpvars[v], branchpriority) );
5454  if( (SCIP_BRANCHDIR)tmpvars[v]->branchdirection == SCIP_BRANCHDIR_AUTO )
5455  {
5456  if( tmpscalars[v] >= 0.0 )
5457  {
5458  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], branchdirection) );
5459  }
5460  else
5461  {
5462  SCIP_CALL( SCIPvarChgBranchDirection(tmpvars[v], SCIPbranchdirOpposite(branchdirection)) );
5463  }
5464  }
5465  }
5466  SCIP_CALL( SCIPvarChgBranchFactor(var, set, branchfactor) );
5467  SCIP_CALL( SCIPvarChgBranchPriority(var, branchpriority) );
5468 
5469  if( var->probindex != -1 )
5470  {
5471  /* inform problem about the variable's status change */
5472  SCIP_CALL( SCIPprobVarChangedStatus(transprob, blkmem, set, branchcand, cliquetable, var) );
5473  }
5474 
5475  /* issue VARFIXED event */
5476  SCIP_CALL( varEventVarFixed(var, blkmem, set, eventqueue, 2) );
5477 
5478  /* reset the objective value of the aggregated variable, thus adjusting the objective value of the aggregation
5479  * variables and the problem's objective offset
5480  */
5481  SCIP_CALL( SCIPvarAddObj(var, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp, eventqueue, obj) );
5482 
5483  *aggregated = TRUE;
5484 
5485  TERMINATE:
5486  BMSfreeBlockMemoryArray(blkmem, &tmpscalars, tmpvarssize);
5487  BMSfreeBlockMemoryArray(blkmem, &tmpvars, tmpvarssize);
5488 
5489  break;
5490 
5491  case SCIP_VARSTATUS_COLUMN:
5492  SCIPerrorMessage("cannot multi-aggregate a column variable\n");
5493  return SCIP_INVALIDDATA;
5494 
5495  case SCIP_VARSTATUS_FIXED:
5496  SCIPerrorMessage("cannot multi-aggregate a fixed variable\n");
5497  return SCIP_INVALIDDATA;
5498 
5500  SCIPerrorMessage("cannot multi-aggregate an aggregated variable\n");
5501  return SCIP_INVALIDDATA;
5502 
5504  SCIPerrorMessage("cannot multi-aggregate a multiple aggregated variable again\n");
5505  return SCIP_INVALIDDATA;
5506 
5508  /* aggregate negation variable x in x' = offset - x, instead of aggregating x' directly:
5509  * x' = a_1*y_1 + ... + a_n*y_n + c -> x = offset - x' = offset - a_1*y_1 - ... - a_n*y_n - c
5510  */
5511  assert(SCIPsetIsZero(set, var->obj));
5512  assert(var->negatedvar != NULL);
5514  assert(var->negatedvar->negatedvar == var);
5515 
5516  /* switch the signs of the aggregation scalars */
5517  for( v = 0; v < naggvars; ++v )
5518  scalars[v] *= -1.0;
5519 
5520  /* perform the multi aggregation on the negation variable */
5521  SCIP_CALL( SCIPvarMultiaggregate(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
5522  cliquetable, branchcand, eventfilter, eventqueue, naggvars, aggvars, scalars,
5523  var->data.negate.constant - constant, infeasible, aggregated) );
5524 
5525  /* switch the signs of the aggregation scalars again, to reset them to their original values */
5526  for( v = 0; v < naggvars; ++v )
5527  scalars[v] *= -1.0;
5528  break;
5529 
5530  default:
5531  SCIPerrorMessage("unknown variable status\n");
5532  return SCIP_INVALIDDATA;
5533  }
5534 
5535  return SCIP_OKAY;
5536 }
5537 
5538 /** transformed variables are resolved to their active, fixed, or multi-aggregated problem variable of a variable,
5539  * or for original variables the same variable is returned
5540  */
5541 static
5543  SCIP_VAR* var /**< problem variable */
5544  )
5545 {
5546  SCIP_VAR* retvar;
5547 
5548  assert(var != NULL);
5549 
5550  retvar = var;
5551 
5552  SCIPdebugMessage("get active variable of <%s>\n", var->name);
5553 
5554  while( TRUE ) /*lint !e716 */
5555  {
5556  assert(retvar != NULL);
5557 
5558  switch( SCIPvarGetStatus(retvar) )
5559  {
5561  case SCIP_VARSTATUS_LOOSE:
5562  case SCIP_VARSTATUS_COLUMN:
5563  case SCIP_VARSTATUS_FIXED:
5564  return retvar;
5565 
5567  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
5568  if ( retvar->data.multaggr.nvars == 1 )
5569  retvar = retvar->data.multaggr.vars[0];
5570  else
5571  return retvar;
5572  break;
5573 
5575  retvar = retvar->data.aggregate.var;
5576  break;
5577 
5579  retvar = retvar->negatedvar;
5580  break;
5581 
5582  default:
5583  SCIPerrorMessage("unknown variable status\n");
5584  SCIPABORT();
5585  return NULL; /*lint !e527*/
5586  }
5587  }
5588 }
5589 
5590 /** returns whether variable is not allowed to be multi-aggregated */
5592  SCIP_VAR* var /**< problem variable */
5593  )
5594 {
5595  SCIP_VAR* retvar;
5596 
5597  assert(var != NULL);
5598 
5599  retvar = varGetActiveVar(var);
5600  assert(retvar != NULL);
5601 
5602  switch( SCIPvarGetStatus(retvar) )
5603  {
5605  case SCIP_VARSTATUS_LOOSE:
5606  case SCIP_VARSTATUS_COLUMN:
5607  case SCIP_VARSTATUS_FIXED:
5608  return retvar->donotmultaggr;
5609 
5611  return FALSE;
5612 
5615  default:
5616  SCIPerrorMessage("wrong variable status\n");
5617  SCIPABORT();
5618  return FALSE; /*lint !e527 */
5619  }
5620 }
5621 
5622 /** gets negated variable x' = offset - x of problem variable x; the negated variable is created if not yet existing;
5623  * the negation offset of binary variables is always 1, the offset of other variables is fixed to lb + ub when the
5624  * negated variable is created
5625  */
5627  SCIP_VAR* var, /**< problem variable to negate */
5628  BMS_BLKMEM* blkmem, /**< block memory of transformed problem */
5629  SCIP_SET* set, /**< global SCIP settings */
5630  SCIP_STAT* stat, /**< problem statistics */
5631  SCIP_VAR** negvar /**< pointer to store the negated variable */
5632  )
5633 {
5634  assert(var != NULL);
5635  assert(var->scip == set->scip);
5636  assert(negvar != NULL);
5637 
5638  /* check, if we already created the negated variable */
5639  if( var->negatedvar == NULL )
5640  {
5641  char negvarname[SCIP_MAXSTRLEN];
5642 
5643  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED);
5644 
5645  SCIPsetDebugMsg(set, "creating negated variable of <%s>\n", var->name);
5646 
5647  /* negation is only possible for bounded variables */
5648  if( SCIPsetIsInfinity(set, -var->glbdom.lb) || SCIPsetIsInfinity(set, var->glbdom.ub) )
5649  {
5650  SCIPerrorMessage("cannot negate unbounded variable\n");
5651  return SCIP_INVALIDDATA;
5652  }
5653 
5654  (void) SCIPsnprintf(negvarname, SCIP_MAXSTRLEN, "%s_neg", var->name);
5655 
5656  /* create negated variable */
5657  SCIP_CALL( varCreate(negvar, blkmem, set, stat, negvarname, var->glbdom.lb, var->glbdom.ub, 0.0,
5658  SCIPvarGetType(var), var->initial, var->removable, NULL, NULL, NULL, NULL, NULL) );
5659  (*negvar)->varstatus = SCIP_VARSTATUS_NEGATED; /*lint !e641*/
5660  if( SCIPvarIsBinary(var) )
5661  (*negvar)->data.negate.constant = 1.0;
5662  else
5663  (*negvar)->data.negate.constant = var->glbdom.lb + var->glbdom.ub;
5664 
5665  /* create event filter for transformed variable */
5666  if( SCIPvarIsTransformed(var) )
5667  {
5668  SCIP_CALL( SCIPeventfilterCreate(&(*negvar)->eventfilter, blkmem) );
5669  }
5670 
5671  /* set the bounds corresponding to the negation variable */
5672  (*negvar)->glbdom.lb = (*negvar)->data.negate.constant - var->glbdom.ub;
5673  (*negvar)->glbdom.ub = (*negvar)->data.negate.constant - var->glbdom.lb;
5674  (*negvar)->locdom.lb = (*negvar)->data.negate.constant - var->locdom.ub;
5675  (*negvar)->locdom.ub = (*negvar)->data.negate.constant - var->locdom.lb;
5676  /**@todo create holes in the negated variable corresponding to the holes of the negation variable */
5677 
5678  /* link the variables together */
5679  var->negatedvar = *negvar;
5680  (*negvar)->negatedvar = var;
5681 
5682  /* mark both variables to be non-deletable */
5684  SCIPvarMarkNotDeletable(*negvar);
5685 
5686  /* copy the branch factor and priority, and use the negative preferred branching direction */
5687  (*negvar)->branchfactor = var->branchfactor;
5688  (*negvar)->branchpriority = var->branchpriority;
5689  (*negvar)->branchdirection = SCIPbranchdirOpposite((SCIP_BRANCHDIR)var->branchdirection); /*lint !e641*/
5690 
5691  /* copy doNotMultiaggr status */
5692  (*negvar)->donotmultaggr = var->donotmultaggr;
5693 
5694  /* copy lazy bounds (they have to be flipped) */
5695  (*negvar)->lazylb = (*negvar)->data.negate.constant - var->lazyub;
5696  (*negvar)->lazyub = (*negvar)->data.negate.constant - var->lazylb;
5697 
5698  /* make negated variable a parent of the negation variable (negated variable is captured as a parent) */
5699  SCIP_CALL( varAddParent(var, blkmem, set, *negvar) );
5700  assert((*negvar)->nuses == 1);
5701  }
5702  assert(var->negatedvar != NULL);
5703 
5704  /* return the negated variable */
5705  *negvar = var->negatedvar;
5706 
5707  /* exactly one variable of the negation pair has to be marked as negated variable */
5709 
5710  return SCIP_OKAY;
5711 }
5712 
5713 /** informs variable that its position in problem's vars array changed */
5714 static
5715 void varSetProbindex(
5716  SCIP_VAR* var, /**< problem variable */
5717  int probindex /**< new problem index of variable (-1 for removal) */
5718  )
5719 {
5720  assert(var != NULL);
5721  assert(probindex >= 0 || var->vlbs == NULL);
5722  assert(probindex >= 0 || var->vubs == NULL);
5723  assert(probindex >= 0 || var->implics == NULL);
5724 
5725  var->probindex = probindex;
5727  {
5728  assert(var->data.col != NULL);
5729  var->data.col->var_probindex = probindex;
5730  }
5731 }
5732 
5733 /** informs variable that its position in problem's vars array changed */
5734 void SCIPvarSetProbindex(
5735  SCIP_VAR* var, /**< problem variable */
5736  int probindex /**< new problem index of variable */
5737  )
5738 {
5739  assert(var != NULL);
5740  assert(probindex >= 0);
5741 
5742  varSetProbindex(var, probindex);
5743 }
5744 
5745 /** gives the variable a new name
5746  *
5747  * @note the old pointer is overwritten, which might result in a memory leakage
5748  */
5750  SCIP_VAR* var, /**< problem variable */
5751  const char* name /**< new name of variable */
5752  )
5753 {
5754  assert(var != NULL);
5755  assert(name != NULL);
5756 
5757  var->name = (char*)name;
5758 }
5759 
5760 /** informs variable that it will be removed from the problem; adjusts probindex and removes variable from the
5761  * implication graph;
5762  * If 'final' is TRUE, the thorough implication graph removal is not performed. Instead, only the
5763  * variable bounds and implication data structures of the variable are freed. Since in the final removal
5764  * of all variables from the transformed problem, this deletes the implication graph completely and is faster
5765  * than removing the variables one by one, each time updating all lists of the other variables.
5766  */
5768  SCIP_VAR* var, /**< problem variable */
5769  BMS_BLKMEM* blkmem, /**< block memory buffer */
5770  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
5771  SCIP_SET* set, /**< global SCIP settings */
5772  SCIP_Bool final /**< is this the final removal of all problem variables? */
5773  )
5774 {
5775  assert(SCIPvarGetProbindex(var) >= 0);
5776  assert(var->scip == set->scip);
5777 
5778  /* if the variable is active in the transformed problem, remove it from the implication graph */
5779  if( SCIPvarIsTransformed(var)
5781  {
5782  if( final )
5783  {
5784  /* just destroy the data structures */
5785  SCIPvboundsFree(&var->vlbs, blkmem);
5786  SCIPvboundsFree(&var->vubs, blkmem);
5787  SCIPimplicsFree(&var->implics, blkmem);
5788  }
5789  else
5790  {
5791  /* unlink the variable from all other variables' lists and free the data structures */
5792  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, FALSE, TRUE) );
5793  }
5794  }
5795 
5796  /* mark the variable to be no longer a member of the problem */
5797  varSetProbindex(var, -1);
5798 
5799  return SCIP_OKAY;
5800 }
5801 
5802 /** marks the variable to be deleted from the problem */
5803 void SCIPvarMarkDeleted(
5804  SCIP_VAR* var /**< problem variable */
5805  )
5806 {
5807  assert(var != NULL);
5808  assert(var->probindex != -1);
5809 
5810  var->deleted = TRUE;
5811 }
5812 
5813 /** marks the variable to not to be multi-aggregated */
5815  SCIP_VAR* var /**< problem variable */
5816  )
5817 {
5818  SCIP_VAR* retvar;
5819 
5820  assert(var != NULL);
5821 
5822  retvar = varGetActiveVar(var);
5823  assert(retvar != NULL);
5824 
5825  switch( SCIPvarGetStatus(retvar) )
5826  {
5828  case SCIP_VARSTATUS_LOOSE:
5829  case SCIP_VARSTATUS_COLUMN:
5830  case SCIP_VARSTATUS_FIXED:
5831  retvar->donotmultaggr = TRUE;
5832  break;
5833 
5835  SCIPerrorMessage("cannot mark a multi-aggregated variable to not be multi-aggregated.\n");
5836  return SCIP_INVALIDDATA;
5837 
5840  default:
5841  SCIPerrorMessage("wrong variable status\n");
5842  return SCIP_INVALIDDATA;
5843  }
5844 
5845  return SCIP_OKAY;
5846 }
5847 
5848 /** changes type of variable; cannot be called, if var belongs to a problem */
5850  SCIP_VAR* var, /**< problem variable to change */
5851  SCIP_VARTYPE vartype /**< new type of variable */
5852  )
5853 {
5854  assert(var != NULL);
5855 
5856  SCIPdebugMessage("change type of <%s> from %d to %d\n", var->name, SCIPvarGetType(var), vartype);
5857 
5858  if( var->probindex >= 0 )
5859  {
5860  SCIPerrorMessage("cannot change type of variable already in the problem\n");
5861  return SCIP_INVALIDDATA;
5862  }
5863 
5864  var->vartype = vartype; /*lint !e641*/
5865  if( var->negatedvar != NULL )
5866  var->negatedvar->vartype = vartype; /*lint !e641*/
5867 
5868  return SCIP_OKAY;
5869 }
5870 
5871 /** appends OBJCHANGED event to the event queue */
5872 static
5874  SCIP_VAR* var, /**< problem variable to change */
5875  BMS_BLKMEM* blkmem, /**< block memory */
5876  SCIP_SET* set, /**< global SCIP settings */
5877  SCIP_PRIMAL* primal, /**< primal data */
5878  SCIP_LP* lp, /**< current LP data */
5879  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5880  SCIP_Real oldobj, /**< old objective value for variable */
5881  SCIP_Real newobj /**< new objective value for variable */
5882  )
5883 {
5884  SCIP_EVENT* event;
5885 
5886  assert(var != NULL);
5887  assert(var->scip == set->scip);
5888  assert(var->eventfilter != NULL);
5890  assert(SCIPvarIsTransformed(var));
5891  assert(!SCIPsetIsEQ(set, oldobj, newobj));
5892 
5893  SCIP_CALL( SCIPeventCreateObjChanged(&event, blkmem, var, oldobj, newobj) );
5894  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, primal, lp, NULL, NULL, &event) );
5895 
5896  return SCIP_OKAY;
5897 }
5898 
5899 /** changes objective value of variable */
5901  SCIP_VAR* var, /**< variable to change */
5902  BMS_BLKMEM* blkmem, /**< block memory */
5903  SCIP_SET* set, /**< global SCIP settings */
5904  SCIP_PROB* prob, /**< problem data */
5905  SCIP_PRIMAL* primal, /**< primal data */
5906  SCIP_LP* lp, /**< current LP data */
5907  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5908  SCIP_Real newobj /**< new objective value for variable */
5909  )
5910 {
5911  SCIP_Real oldobj;
5912 
5913  assert(var != NULL);
5914  assert(set != NULL);
5915  assert(var->scip == set->scip);
5916 
5917  SCIPsetDebugMsg(set, "changing objective value of <%s> from %g to %g\n", var->name, var->obj, newobj);
5918 
5919  if( !SCIPsetIsEQ(set, var->obj, newobj) )
5920  {
5921  switch( SCIPvarGetStatus(var) )
5922  {
5924  if( var->data.original.transvar != NULL )
5925  {
5926  assert(SCIPprobIsTransformed(prob));
5927 
5928  SCIP_CALL( SCIPvarChgObj(var->data.original.transvar, blkmem, set, prob, primal, lp, eventqueue,
5929  (SCIP_Real) prob->objsense * newobj/prob->objscale) );
5930  }
5931  else
5932  assert(set->stage == SCIP_STAGE_PROBLEM);
5933 
5934  var->obj = newobj;
5935  var->unchangedobj = newobj;
5936 
5937  break;
5938 
5939  case SCIP_VARSTATUS_LOOSE:
5940  case SCIP_VARSTATUS_COLUMN:
5941  oldobj = var->obj;
5942  var->obj = newobj;
5943 
5944  /* update unchanged objective value of variable */
5945  if( !lp->divingobjchg )
5946  var->unchangedobj = newobj;
5947 
5948  /* update the number of variables with non-zero objective coefficient;
5949  * we only want to do the update, if the variable is added to the problem;
5950  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
5951  */
5952  if( SCIPvarIsActive(var) )
5953  SCIPprobUpdateNObjVars(prob, set, oldobj, var->obj);
5954 
5955  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
5956  break;
5957 
5958  case SCIP_VARSTATUS_FIXED:
5962  SCIPerrorMessage("cannot change objective value of a fixed, aggregated, multi-aggregated, or negated variable\n");
5963  return SCIP_INVALIDDATA;
5964 
5965  default:
5966  SCIPerrorMessage("unknown variable status\n");
5967  return SCIP_INVALIDDATA;
5968  }
5969  }
5970 
5971  return SCIP_OKAY;
5972 }
5973 
5974 /** adds value to objective value of variable */
5976  SCIP_VAR* var, /**< variable to change */
5977  BMS_BLKMEM* blkmem, /**< block memory */
5978  SCIP_SET* set, /**< global SCIP settings */
5979  SCIP_STAT* stat, /**< problem statistics */
5980  SCIP_PROB* transprob, /**< transformed problem data */
5981  SCIP_PROB* origprob, /**< original problem data */
5982  SCIP_PRIMAL* primal, /**< primal data */
5983  SCIP_TREE* tree, /**< branch and bound tree */
5984  SCIP_REOPT* reopt, /**< reoptimization data structure */
5985  SCIP_LP* lp, /**< current LP data */
5986  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
5987  SCIP_Real addobj /**< additional objective value for variable */
5988  )
5989 {
5990  assert(var != NULL);
5991  assert(set != NULL);
5992  assert(var->scip == set->scip);
5993  assert(set->stage < SCIP_STAGE_INITSOLVE);
5994 
5995  SCIPsetDebugMsg(set, "adding %g to objective value %g of <%s>\n", addobj, var->obj, var->name);
5996 
5997  if( !SCIPsetIsZero(set, addobj) )
5998  {
5999  SCIP_Real oldobj;
6000  int i;
6001 
6002  switch( SCIPvarGetStatus(var) )
6003  {
6005  if( var->data.original.transvar != NULL )
6006  {
6007  SCIP_CALL( SCIPvarAddObj(var->data.original.transvar, blkmem, set, stat, transprob, origprob, primal, tree,
6008  reopt, lp, eventqueue, (SCIP_Real) transprob->objsense * addobj/transprob->objscale) );
6009  }
6010  else
6011  assert(set->stage == SCIP_STAGE_PROBLEM);
6012 
6013  var->obj += addobj;
6014  var->unchangedobj += addobj;
6015  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6016 
6017  break;
6018 
6019  case SCIP_VARSTATUS_LOOSE:
6020  case SCIP_VARSTATUS_COLUMN:
6021  oldobj = var->obj;
6022  var->obj += addobj;
6023 
6024  /* update unchanged objective value of variable */
6025  if( !lp->divingobjchg )
6026  {
6027  var->unchangedobj += addobj;
6028  assert(SCIPsetIsEQ(set, var->obj, var->unchangedobj));
6029  }
6030 
6031  /* update the number of variables with non-zero objective coefficient;
6032  * we only want to do the update, if the variable is added to the problem;
6033  * since the objective of inactive variables cannot be changed, this corresponds to probindex != -1
6034  */
6035  if( SCIPvarIsActive(var) )
6036  SCIPprobUpdateNObjVars(transprob, set, oldobj, var->obj);
6037 
6038  SCIP_CALL( varEventObjChanged(var, blkmem, set, primal, lp, eventqueue, oldobj, var->obj) );
6039  break;
6040 
6041  case SCIP_VARSTATUS_FIXED:
6042  assert(SCIPsetIsEQ(set, var->locdom.lb, var->locdom.ub));
6043  SCIPprobAddObjoffset(transprob, var->locdom.lb * addobj);
6044  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6045  break;
6046 
6048  /* x = a*y + c -> add a*addobj to obj. val. of y, and c*addobj to obj. offset of problem */
6049  SCIPprobAddObjoffset(transprob, var->data.aggregate.constant * addobj);
6050  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6051  SCIP_CALL( SCIPvarAddObj(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, primal, tree, reopt,
6052  lp, eventqueue, var->data.aggregate.scalar * addobj) );
6053  break;
6054 
6056  assert(!var->donotmultaggr);
6057  /* 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 */
6058  SCIPprobAddObjoffset(transprob, var->data.multaggr.constant * addobj);
6059  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6060  for( i = 0; i < var->data.multaggr.nvars; ++i )
6061  {
6062  SCIP_CALL( SCIPvarAddObj(var->data.multaggr.vars[i], blkmem, set, stat, transprob, origprob, primal, tree,
6063  reopt, lp, eventqueue, var->data.multaggr.scalars[i] * addobj) );
6064  }
6065  break;
6066 
6068  /* x' = offset - x -> add -addobj to obj. val. of x and offset*addobj to obj. offset of problem */
6069  assert(var->negatedvar != NULL);
6071  assert(var->negatedvar->negatedvar == var);
6072  SCIPprobAddObjoffset(transprob, var->data.negate.constant * addobj);
6073  SCIP_CALL( SCIPprimalUpdateObjoffset(primal, blkmem, set, stat, eventqueue, transprob, origprob, tree, reopt, lp) );
6074  SCIP_CALL( SCIPvarAddObj(var->negatedvar, blkmem, set, stat, transprob, origprob, primal, tree, reopt, lp,
6075  eventqueue, -addobj) );
6076  break;
6077 
6078  default:
6079  SCIPerrorMessage("unknown variable status\n");
6080  return SCIP_INVALIDDATA;
6081  }
6082  }
6083 
6084  return SCIP_OKAY;
6085 }
6086 
6087 /** changes objective value of variable in current dive */
6089  SCIP_VAR* var, /**< problem variable to change */
6090  SCIP_SET* set, /**< global SCIP settings */
6091  SCIP_LP* lp, /**< current LP data */
6092  SCIP_Real newobj /**< new objective value for variable */
6093  )
6094 {
6095  assert(var != NULL);
6096  assert(set != NULL);
6097  assert(var->scip == set->scip);
6098  assert(lp != NULL);
6099 
6100  SCIPsetDebugMsg(set, "changing objective of <%s> to %g in current dive\n", var->name, newobj);
6101 
6102  if( SCIPsetIsZero(set, newobj) )
6103  newobj = 0.0;
6104 
6105  /* change objective value of attached variables */
6106  switch( SCIPvarGetStatus(var) )
6107  {
6109  assert(var->data.original.transvar != NULL);
6110  SCIP_CALL( SCIPvarChgObjDive(var->data.original.transvar, set, lp, newobj) );
6111  break;
6112 
6113  case SCIP_VARSTATUS_COLUMN:
6114  assert(var->data.col != NULL);
6115  SCIP_CALL( SCIPcolChgObj(var->data.col, set, lp, newobj) );
6116  break;
6117 
6118  case SCIP_VARSTATUS_LOOSE:
6119  case SCIP_VARSTATUS_FIXED:
6120  /* nothing to do here: only the constant shift in objective function would change */
6121  break;
6122 
6123  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6124  assert(var->data.aggregate.var != NULL);
6125  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
6126  SCIP_CALL( SCIPvarChgObjDive(var->data.aggregate.var, set, lp, newobj / var->data.aggregate.scalar) );
6127  /* the constant can be ignored, because it would only affect the objective shift */
6128  break;
6129 
6131  SCIPerrorMessage("cannot change diving objective value of a multi-aggregated variable\n");
6132  return SCIP_INVALIDDATA;
6133 
6134  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6135  assert(var->negatedvar != NULL);
6137  assert(var->negatedvar->negatedvar == var);
6138  SCIP_CALL( SCIPvarChgObjDive(var->negatedvar, set, lp, -newobj) );
6139  /* the offset can be ignored, because it would only affect the objective shift */
6140  break;
6141 
6142  default:
6143  SCIPerrorMessage("unknown variable status\n");
6144  return SCIP_INVALIDDATA;
6145  }
6146 
6147  return SCIP_OKAY;
6148 }
6149 
6150 /** adjust lower bound to integral value, if variable is integral */
6151 void SCIPvarAdjustLb(
6152  SCIP_VAR* var, /**< problem variable */
6153  SCIP_SET* set, /**< global SCIP settings */
6154  SCIP_Real* lb /**< pointer to lower bound to adjust */
6155  )
6156 {
6157  assert(var != NULL);
6158  assert(set != NULL);
6159  assert(var->scip == set->scip);
6160  assert(lb != NULL);
6161 
6162  SCIPsetDebugMsg(set, "adjust lower bound %g of <%s>\n", *lb, var->name);
6163 
6164  *lb = adjustedLb(set, SCIPvarGetType(var), *lb);
6165 }
6166 
6167 /** adjust upper bound to integral value, if variable is integral */
6168 void SCIPvarAdjustUb(
6169  SCIP_VAR* var, /**< problem variable */
6170  SCIP_SET* set, /**< global SCIP settings */
6171  SCIP_Real* ub /**< pointer to upper bound to adjust */
6172  )
6173 {
6174  assert(var != NULL);
6175  assert(set != NULL);
6176  assert(var->scip == set->scip);
6177  assert(ub != NULL);
6178 
6179  SCIPsetDebugMsg(set, "adjust upper bound %g of <%s>\n", *ub, var->name);
6180 
6181  *ub = adjustedUb(set, SCIPvarGetType(var), *ub);
6182 }
6183 
6184 /** adjust lower or upper bound to integral value, if variable is integral */
6185 void SCIPvarAdjustBd(
6186  SCIP_VAR* var, /**< problem variable */
6187  SCIP_SET* set, /**< global SCIP settings */
6188  SCIP_BOUNDTYPE boundtype, /**< type of bound to adjust */
6189  SCIP_Real* bd /**< pointer to bound to adjust */
6190  )
6191 {
6192  assert(boundtype == SCIP_BOUNDTYPE_LOWER || boundtype == SCIP_BOUNDTYPE_UPPER);
6193 
6194  if( boundtype == SCIP_BOUNDTYPE_LOWER )
6195  SCIPvarAdjustLb(var, set, bd);
6196  else
6197  SCIPvarAdjustUb(var, set, bd);
6198 }
6199 
6200 /** changes lower bound of original variable in original problem */
6202  SCIP_VAR* var, /**< problem variable to change */
6203  SCIP_SET* set, /**< global SCIP settings */
6204  SCIP_Real newbound /**< new bound for variable */
6205  )
6206 {
6207  int i;
6208 
6209  assert(var != NULL);
6210  assert(!SCIPvarIsTransformed(var));
6212  assert(set != NULL);
6213  assert(var->scip == set->scip);
6214  assert(set->stage == SCIP_STAGE_PROBLEM);
6215 
6216  /* check that the bound is feasible */
6217  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, SCIPvarGetUbOriginal(var)));
6218  /* adjust bound to integral value if variable is of integral type */
6219  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6220 
6221  if( SCIPsetIsZero(set, newbound) )
6222  newbound = 0.0;
6223 
6224  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6226  {
6227  SCIPsetDebugMsg(set, "changing original lower bound of <%s> from %g to %g\n",
6228  var->name, var->data.original.origdom.lb, newbound);
6229 
6230  if( SCIPsetIsEQ(set, var->data.original.origdom.lb, newbound) )
6231  return SCIP_OKAY;
6232 
6233  /* change the bound */
6234  var->data.original.origdom.lb = newbound;
6235  }
6236  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6237  {
6238  assert( var->negatedvar != NULL );
6239  SCIP_CALL( SCIPvarChgUbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6240  }
6241 
6242  /* process parent variables */
6243  for( i = 0; i < var->nparentvars; ++i )
6244  {
6245  SCIP_VAR* parentvar;
6246 
6247  parentvar = var->parentvars[i];
6248  assert(parentvar != NULL);
6249  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6250  assert(parentvar->negatedvar == var);
6251  assert(var->negatedvar == parentvar);
6252 
6253  SCIP_CALL( SCIPvarChgUbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6254  }
6255 
6256  return SCIP_OKAY;
6257 }
6258 
6259 /** changes upper bound of original variable in original problem */
6261  SCIP_VAR* var, /**< problem variable to change */
6262  SCIP_SET* set, /**< global SCIP settings */
6263  SCIP_Real newbound /**< new bound for variable */
6264  )
6265 {
6266  int i;
6267 
6268  assert(var != NULL);
6269  assert(!SCIPvarIsTransformed(var));
6271  assert(set != NULL);
6272  assert(var->scip == set->scip);
6273  assert(set->stage == SCIP_STAGE_PROBLEM);
6274 
6275  /* check that the bound is feasible */
6276  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, SCIPvarGetLbOriginal(var)));
6277  /* adjust bound to integral value if variable is of integral type */
6278  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6279 
6280  if( SCIPsetIsZero(set, newbound) )
6281  newbound = 0.0;
6282 
6283  /* original domains are only stored for ORIGINAL variables, not for NEGATED */
6285  {
6286  SCIPsetDebugMsg(set, "changing original upper bound of <%s> from %g to %g\n",
6287  var->name, var->data.original.origdom.ub, newbound);
6288 
6289  if( SCIPsetIsEQ(set, var->data.original.origdom.ub, newbound) )
6290  return SCIP_OKAY;
6291 
6292  /* change the bound */
6293  var->data.original.origdom.ub = newbound;
6294  }
6295  else if( SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED )
6296  {
6297  assert( var->negatedvar != NULL );
6298  SCIP_CALL( SCIPvarChgLbOriginal(var->negatedvar, set, var->data.negate.constant - newbound) );
6299  }
6300 
6301  /* process parent variables */
6302  for( i = 0; i < var->nparentvars; ++i )
6303  {
6304  SCIP_VAR* parentvar;
6305 
6306  parentvar = var->parentvars[i];
6307  assert(parentvar != NULL);
6308  assert(SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_NEGATED);
6309  assert(parentvar->negatedvar == var);
6310  assert(var->negatedvar == parentvar);
6311 
6312  SCIP_CALL( SCIPvarChgLbOriginal(parentvar, set, parentvar->data.negate.constant - newbound) );
6313  }
6314 
6315  return SCIP_OKAY;
6316 }
6317 
6318 /** appends GLBCHANGED event to the event queue */
6319 static
6321  SCIP_VAR* var, /**< problem variable to change */
6322  BMS_BLKMEM* blkmem, /**< block memory */
6323  SCIP_SET* set, /**< global SCIP settings */
6324  SCIP_LP* lp, /**< current LP data */
6325  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6326  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6327  SCIP_Real oldbound, /**< old lower bound for variable */
6328  SCIP_Real newbound /**< new lower bound for variable */
6329  )
6330 {
6331  assert(var != NULL);
6332  assert(var->eventfilter != NULL);
6333  assert(SCIPvarIsTransformed(var));
6334  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6335  assert(set != NULL);
6336  assert(var->scip == set->scip);
6337 
6338  /* check, if the variable is being tracked for bound changes
6339  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6340  */
6341  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GLBCHANGED) != 0)
6344  {
6345  SCIP_EVENT* event;
6346 
6347  SCIPsetDebugMsg(set, "issue GLBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6348 
6349  SCIP_CALL( SCIPeventCreateGlbChanged(&event, blkmem, var, oldbound, newbound) );
6350  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6351  }
6352 
6353  return SCIP_OKAY;
6354 }
6355 
6356 /** appends GUBCHANGED event to the event queue */
6357 static
6359  SCIP_VAR* var, /**< problem variable to change */
6360  BMS_BLKMEM* blkmem, /**< block memory */
6361  SCIP_SET* set, /**< global SCIP settings */
6362  SCIP_LP* lp, /**< current LP data */
6363  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
6364  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6365  SCIP_Real oldbound, /**< old lower bound for variable */
6366  SCIP_Real newbound /**< new lower bound for variable */
6367  )
6368 {
6369  assert(var != NULL);
6370  assert(var->eventfilter != NULL);
6371  assert(SCIPvarIsTransformed(var));
6372  assert(!SCIPsetIsEQ(set, oldbound, newbound));
6373  assert(set != NULL);
6374  assert(var->scip == set->scip);
6375 
6376  /* check, if the variable is being tracked for bound changes
6377  * COLUMN and LOOSE variables are tracked always, because global/root pseudo objective value has to be updated
6378  */
6379  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GUBCHANGED) != 0)
6382  {
6383  SCIP_EVENT* event;
6384 
6385  SCIPsetDebugMsg(set, "issue GUBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
6386 
6387  SCIP_CALL( SCIPeventCreateGubChanged(&event, blkmem, var, oldbound, newbound) );
6388  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
6389  }
6390 
6391  return SCIP_OKAY;
6392 }
6393 
6394 /** appends GHOLEADDED event to the event queue */
6395 static
6397  SCIP_VAR* var, /**< problem variable to change */
6398  BMS_BLKMEM* blkmem, /**< block memory */
6399  SCIP_SET* set, /**< global SCIP settings */
6400  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
6401  SCIP_Real left, /**< left bound of open interval in new hole */
6402  SCIP_Real right /**< right bound of open interval in new hole */
6403  )
6404 {
6405  assert(var != NULL);
6406  assert(var->eventfilter != NULL);
6407  assert(SCIPvarIsTransformed(var));
6408  assert(set != NULL);
6409  assert(var->scip == set->scip);
6410  assert(SCIPsetIsLT(set, left, right));
6411 
6412  /* check, if the variable is being tracked for bound changes */
6413  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_GHOLEADDED) != 0) )
6414  {
6415  SCIP_EVENT* event;
6416 
6417  SCIPsetDebugMsg(set, "issue GHOLEADDED event for variable <%s>: (%.15g,%.15g)\n", var->name, left, right);
6418 
6419  SCIP_CALL( SCIPeventCreateGholeAdded(&event, blkmem, var, left, right) );
6420  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
6421  }
6422 
6423  return SCIP_OKAY;
6424 }
6425 
6426 /** increases root bound change statistics after a global bound change */
6427 static
6428 void varIncRootboundchgs(
6429  SCIP_VAR* var, /**< problem variable to change */
6430  SCIP_SET* set, /**< global SCIP settings */
6431  SCIP_STAT* stat /**< problem statistics */
6432  )
6433 {
6434  assert(var != NULL);
6435  assert(set != NULL);
6436  assert(var->scip == set->scip);
6437  assert(stat != NULL);
6438 
6439  if( SCIPvarIsActive(var) && SCIPvarIsTransformed(var) && set->stage == SCIP_STAGE_SOLVING )
6440  {
6441  stat->nrootboundchgs++;
6442  stat->nrootboundchgsrun++;
6443  if( SCIPvarIsIntegral(var) && SCIPvarGetLbGlobal(var) + 0.5 > SCIPvarGetUbGlobal(var) )
6444  {
6445  stat->nrootintfixings++;
6446  stat->nrootintfixingsrun++;
6447  }
6448  }
6449 }
6450 
6451 /* forward declaration, because both methods call each other recursively */
6452 
6453 /* performs the current change in upper bound, changes all parents accordingly */
6454 static
6456  SCIP_VAR* var, /**< problem variable to change */
6457  BMS_BLKMEM* blkmem, /**< block memory */
6458  SCIP_SET* set, /**< global SCIP settings */
6459  SCIP_STAT* stat, /**< problem statistics */
6460  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6461  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6462  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6463  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6464  SCIP_Real newbound /**< new bound for variable */
6465  );
6466 
6467 /** performs the current change in lower bound, changes all parents accordingly */
6468 static
6470  SCIP_VAR* var, /**< problem variable to change */
6471  BMS_BLKMEM* blkmem, /**< block memory */
6472  SCIP_SET* set, /**< global SCIP settings */
6473  SCIP_STAT* stat, /**< problem statistics */
6474  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6475  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6476  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6477  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6478  SCIP_Real newbound /**< new bound for variable */
6479  )
6480 {
6481  SCIP_VAR* parentvar;
6482  SCIP_Real oldbound;
6483  int i;
6484 
6485  assert(var != NULL);
6486  /* local domains can violate global bounds but not more than feasibility epsilon */
6487  assert(SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb));
6488  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6489  assert(blkmem != NULL);
6490  assert(set != NULL);
6491  assert(var->scip == set->scip);
6492  assert(stat != NULL);
6493 
6494  /* adjust bound to integral value if variable is of integral type */
6495  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6496 
6497  /* check that the bound is feasible */
6498  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound > var->glbdom.ub )
6499  {
6500  /* due to numerics we only want to be feasible in feasibility tolerance */
6501  assert(SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6502  newbound = var->glbdom.ub;
6503  }
6504  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6505 
6506  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6507 
6508  SCIPsetDebugMsg(set, "process changing global lower bound of <%s> from %f to %f\n", var->name, var->glbdom.lb, newbound);
6509 
6510  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) )
6511  return SCIP_OKAY;
6512 
6513  /* check bound on debugging solution */
6514  SCIP_CALL( SCIPdebugCheckLbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6515 
6516  /* change the bound */
6517  oldbound = var->glbdom.lb;
6518  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->glbdom.ub));
6519  var->glbdom.lb = newbound;
6520  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6521  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6522 
6523  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6524  {
6525  /* merges overlapping holes into single holes, moves bounds respectively */
6526  domMerge(&var->glbdom, blkmem, set, &newbound, NULL);
6527  }
6528 
6529  /* update the root bound changes counters */
6530  varIncRootboundchgs(var, set, stat);
6531 
6532  /* update the lbchginfos array by replacing worse local bounds with the new global bound and changing the
6533  * redundant bound changes to be branching decisions
6534  */
6535  for( i = 0; i < var->nlbchginfos; ++i )
6536  {
6537  assert(var->lbchginfos[i].var == var);
6538 
6539  if( var->lbchginfos[i].oldbound < var->glbdom.lb )
6540  {
6541  SCIPsetDebugMsg(set, " -> adjust lower bound change <%s>: %g -> %g due to new global lower bound %g\n",
6542  SCIPvarGetName(var), var->lbchginfos[i].oldbound, var->lbchginfos[i].newbound, var->glbdom.lb);
6543  var->lbchginfos[i].oldbound = var->glbdom.lb;
6544  if( SCIPsetIsLE(set, var->lbchginfos[i].newbound, var->glbdom.lb) )
6545  {
6546  /* this bound change is redundant due to the new global bound */
6547  var->lbchginfos[i].newbound = var->glbdom.lb;
6548  var->lbchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6549  var->lbchginfos[i].redundant = TRUE;
6550  }
6551  else
6552  break; /* from now on, the remaining local bound changes are not redundant */
6553  }
6554  else
6555  break; /* from now on, the remaining local bound changes are not redundant */
6556  }
6557 
6558  /* remove redundant implications and variable bounds */
6560  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6561  {
6562  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6563  }
6564 
6565  /* issue bound change event */
6566  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6567  if( var->eventfilter != NULL )
6568  {
6569  SCIP_CALL( varEventGlbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6570  }
6571 
6572  /* process parent variables */
6573  for( i = 0; i < var->nparentvars; ++i )
6574  {
6575  parentvar = var->parentvars[i];
6576  assert(parentvar != NULL);
6577 
6578  switch( SCIPvarGetStatus(parentvar) )
6579  {
6581  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6582  break;
6583 
6584  case SCIP_VARSTATUS_COLUMN:
6585  case SCIP_VARSTATUS_LOOSE:
6586  case SCIP_VARSTATUS_FIXED:
6588  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6589  return SCIP_INVALIDDATA;
6590 
6591  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6592  assert(parentvar->data.aggregate.var == var);
6593  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6594  {
6595  SCIP_Real parentnewbound;
6596 
6597  /* a > 0 -> change lower bound of y */
6598  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, -oldbound))
6599  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6600  || (SCIPsetIsZero(set, parentvar->glbdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6601 
6602  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6603  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6604  else
6605  parentnewbound = newbound;
6606  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6607  }
6608  else
6609  {
6610  SCIP_Real parentnewbound;
6611 
6612  /* a < 0 -> change upper bound of y */
6613  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6614  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, -oldbound))
6615  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
6616  || (SCIPsetIsZero(set, parentvar->glbdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
6617 
6618  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6619  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6620  else
6621  parentnewbound = -newbound;
6622  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6623  }
6624  break;
6625 
6626  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6627  assert(parentvar->negatedvar != NULL);
6628  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6629  assert(parentvar->negatedvar->negatedvar == parentvar);
6630  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6631  parentvar->data.negate.constant - newbound) );
6632  break;
6633 
6634  default:
6635  SCIPerrorMessage("unknown variable status\n");
6636  return SCIP_INVALIDDATA;
6637  }
6638  }
6639 
6640  return SCIP_OKAY;
6641 }
6642 
6643 /** performs the current change in upper bound, changes all parents accordingly */
6644 static
6646  SCIP_VAR* var, /**< problem variable to change */
6647  BMS_BLKMEM* blkmem, /**< block memory */
6648  SCIP_SET* set, /**< global SCIP settings */
6649  SCIP_STAT* stat, /**< problem statistics */
6650  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6651  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6652  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6653  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6654  SCIP_Real newbound /**< new bound for variable */
6655  )
6656 {
6657  SCIP_VAR* parentvar;
6658  SCIP_Real oldbound;
6659  int i;
6660 
6661  assert(var != NULL);
6662  /* local domains can violate global bounds but not more than feasibility epsilon */
6663  assert(SCIPsetIsFeasLE(set, var->glbdom.lb , var->locdom.lb));
6664  assert(SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub));
6665  assert(blkmem != NULL);
6666  assert(set != NULL);
6667  assert(var->scip == set->scip);
6668  assert(stat != NULL);
6669 
6670  /* adjust bound to integral value if variable is of integral type */
6671  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6672 
6673  /* check that the bound is feasible */
6674  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM && newbound < var->glbdom.lb )
6675  {
6676  /* due to numerics we only want to be feasible in feasibility tolerance */
6677  assert(SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6678  newbound = var->glbdom.lb;
6679  }
6680  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6681 
6682  assert(var->vartype != SCIP_VARTYPE_BINARY || SCIPsetIsEQ(set, newbound, 0.0) || SCIPsetIsEQ(set, newbound, 1.0)); /*lint !e641*/
6683 
6684  SCIPsetDebugMsg(set, "process changing global upper bound of <%s> from %f to %f\n", var->name, var->glbdom.ub, newbound);
6685 
6686  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) )
6687  return SCIP_OKAY;
6688 
6689  /* check bound on debugging solution */
6690  SCIP_CALL( SCIPdebugCheckUbGlobal(set->scip, var, newbound) ); /*lint !e506 !e774*/
6691 
6692  /* change the bound */
6693  oldbound = var->glbdom.ub;
6694  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->glbdom.lb));
6695  var->glbdom.ub = newbound;
6696  assert( SCIPsetIsFeasLE(set, var->glbdom.lb, var->locdom.lb) );
6697  assert( SCIPsetIsFeasLE(set, var->locdom.ub, var->glbdom.ub) );
6698 
6699  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6700  {
6701  /* merges overlapping holes into single holes, moves bounds respectively */
6702  domMerge(&var->glbdom, blkmem, set, NULL, &newbound);
6703  }
6704 
6705  /* update the root bound changes counters */
6706  varIncRootboundchgs(var, set, stat);
6707 
6708  /* update the ubchginfos array by replacing worse local bounds with the new global bound and changing the
6709  * redundant bound changes to be branching decisions
6710  */
6711  for( i = 0; i < var->nubchginfos; ++i )
6712  {
6713  assert(var->ubchginfos[i].var == var);
6714  if( var->ubchginfos[i].oldbound > var->glbdom.ub )
6715  {
6716  SCIPsetDebugMsg(set, " -> adjust upper bound change <%s>: %g -> %g due to new global upper bound %g\n",
6717  SCIPvarGetName(var), var->ubchginfos[i].oldbound, var->ubchginfos[i].newbound, var->glbdom.ub);
6718  var->ubchginfos[i].oldbound = var->glbdom.ub;
6719  if( SCIPsetIsGE(set, var->ubchginfos[i].newbound, var->glbdom.ub) )
6720  {
6721  /* this bound change is redundant due to the new global bound */
6722  var->ubchginfos[i].newbound = var->glbdom.ub;
6723  var->ubchginfos[i].boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
6724  var->ubchginfos[i].redundant = TRUE;
6725  }
6726  else
6727  break; /* from now on, the remaining local bound changes are not redundant */
6728  }
6729  else
6730  break; /* from now on, the remaining local bound changes are not redundant */
6731  }
6732 
6733  /* remove redundant implications and variable bounds */
6735  && (!set->reopt_enable || set->stage == SCIP_STAGE_PRESOLVING) )
6736  {
6737  SCIP_CALL( SCIPvarRemoveCliquesImplicsVbs(var, blkmem, cliquetable, set, FALSE, TRUE, TRUE) );
6738  }
6739 
6740  /* issue bound change event */
6741  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
6742  if( var->eventfilter != NULL )
6743  {
6744  SCIP_CALL( varEventGubChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
6745  }
6746 
6747  /* process parent variables */
6748  for( i = 0; i < var->nparentvars; ++i )
6749  {
6750  parentvar = var->parentvars[i];
6751  assert(parentvar != NULL);
6752 
6753  switch( SCIPvarGetStatus(parentvar) )
6754  {
6756  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6757  break;
6758 
6759  case SCIP_VARSTATUS_COLUMN:
6760  case SCIP_VARSTATUS_LOOSE:
6761  case SCIP_VARSTATUS_FIXED:
6763  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
6764  return SCIP_INVALIDDATA;
6765 
6766  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6767  assert(parentvar->data.aggregate.var == var);
6768  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
6769  {
6770  SCIP_Real parentnewbound;
6771 
6772  /* a > 0 -> change upper bound of y */
6773  assert((SCIPsetIsInfinity(set, parentvar->glbdom.ub) && SCIPsetIsInfinity(set, oldbound))
6774  || SCIPsetIsFeasEQ(set, parentvar->glbdom.ub,
6775  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6776  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6777  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6778  else
6779  parentnewbound = newbound;
6780  SCIP_CALL( varProcessChgUbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6781  }
6782  else
6783  {
6784  SCIP_Real parentnewbound;
6785 
6786  /* a < 0 -> change lower bound of y */
6787  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
6788  assert((SCIPsetIsInfinity(set, -parentvar->glbdom.lb) && SCIPsetIsInfinity(set, oldbound))
6789  || SCIPsetIsFeasEQ(set, parentvar->glbdom.lb,
6790  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
6791  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6792  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
6793  else
6794  parentnewbound = -newbound;
6795  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, parentnewbound) );
6796  }
6797  break;
6798 
6799  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6800  assert(parentvar->negatedvar != NULL);
6801  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
6802  assert(parentvar->negatedvar->negatedvar == parentvar);
6803  SCIP_CALL( varProcessChgLbGlobal(parentvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6804  parentvar->data.negate.constant - newbound) );
6805  break;
6806 
6807  default:
6808  SCIPerrorMessage("unknown variable status\n");
6809  return SCIP_INVALIDDATA;
6810  }
6811  }
6812 
6813  return SCIP_OKAY;
6814 }
6815 
6816 /** changes global lower bound of variable; if possible, adjusts bound to integral value;
6817  * updates local lower bound if the global bound is tighter
6818  */
6820  SCIP_VAR* var, /**< problem variable to change */
6821  BMS_BLKMEM* blkmem, /**< block memory */
6822  SCIP_SET* set, /**< global SCIP settings */
6823  SCIP_STAT* stat, /**< problem statistics */
6824  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6825  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6826  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6827  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6828  SCIP_Real newbound /**< new bound for variable */
6829  )
6830 {
6831  assert(var != NULL);
6832  assert(blkmem != NULL);
6833  assert(set != NULL);
6834  assert(var->scip == set->scip);
6835 
6836  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6837  * of the domain within feastol
6838  */
6839  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6840 
6841  /* adjust bound to integral value if variable is of integral type */
6842  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
6843 
6844  /* check that the adjusted bound is feasible
6845  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6846  * here because we reset bounds to their original value!
6847  */
6848  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->glbdom.ub));
6849 
6850  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6851  {
6852  /* we do not want to exceed the upperbound, which could have happened due to numerics */
6853  newbound = MIN(newbound, var->glbdom.ub);
6854  }
6855  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6856 
6857  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
6858  * SCIPvarFix() allows fixings that are outside of the domain within feastol
6859  */
6860  assert(lp == NULL || SCIPsetIsFeasLE(set, var->glbdom.lb, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
6861 
6862  SCIPsetDebugMsg(set, "changing global lower bound of <%s> from %g to %g\n", var->name, var->glbdom.lb, newbound);
6863 
6864  if( SCIPsetIsEQ(set, var->glbdom.lb, newbound) )
6865  return SCIP_OKAY;
6866 
6867  /* change bounds of attached variables */
6868  switch( SCIPvarGetStatus(var) )
6869  {
6871  if( var->data.original.transvar != NULL )
6872  {
6873  SCIP_CALL( SCIPvarChgLbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
6874  cliquetable, newbound) );
6875  }
6876  else
6877  {
6878  assert(set->stage == SCIP_STAGE_PROBLEM);
6879  if( newbound > SCIPvarGetLbLocal(var) )
6880  {
6881  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6882  }
6883  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6884  }
6885  break;
6886 
6887  case SCIP_VARSTATUS_COLUMN:
6888  case SCIP_VARSTATUS_LOOSE:
6889  if( newbound > SCIPvarGetLbLocal(var) )
6890  {
6891  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
6892  }
6893  SCIP_CALL( varProcessChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
6894  break;
6895 
6896  case SCIP_VARSTATUS_FIXED:
6897  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
6898  return SCIP_INVALIDDATA;
6899 
6900  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
6901  assert(var->data.aggregate.var != NULL);
6902  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
6903  {
6904  SCIP_Real childnewbound;
6905 
6906  /* a > 0 -> change lower bound of y */
6907  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
6908  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6910  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6911  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6912  else
6913  childnewbound = newbound;
6914  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6915  childnewbound) );
6916  }
6917  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
6918  {
6919  SCIP_Real childnewbound;
6920 
6921  /* a < 0 -> change upper bound of y */
6922  assert((SCIPsetIsInfinity(set, -var->glbdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
6923  || SCIPsetIsFeasEQ(set, var->glbdom.lb,
6925  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
6926  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
6927  else
6928  childnewbound = -newbound;
6929  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6930  childnewbound) );
6931  }
6932  else
6933  {
6934  SCIPerrorMessage("scalar is zero in aggregation\n");
6935  return SCIP_INVALIDDATA;
6936  }
6937  break;
6938 
6940  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
6941  return SCIP_INVALIDDATA;
6942 
6943  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
6944  assert(var->negatedvar != NULL);
6946  assert(var->negatedvar->negatedvar == var);
6947  SCIP_CALL( SCIPvarChgUbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
6948  var->data.negate.constant - newbound) );
6949  break;
6950 
6951  default:
6952  SCIPerrorMessage("unknown variable status\n");
6953  return SCIP_INVALIDDATA;
6954  }
6955 
6956  return SCIP_OKAY;
6957 }
6958 
6959 /** changes global upper bound of variable; if possible, adjusts bound to integral value;
6960  * updates local upper bound if the global bound is tighter
6961  */
6963  SCIP_VAR* var, /**< problem variable to change */
6964  BMS_BLKMEM* blkmem, /**< block memory */
6965  SCIP_SET* set, /**< global SCIP settings */
6966  SCIP_STAT* stat, /**< problem statistics */
6967  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
6968  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
6969  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
6970  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
6971  SCIP_Real newbound /**< new bound for variable */
6972  )
6973 {
6974  assert(var != NULL);
6975  assert(blkmem != NULL);
6976  assert(set != NULL);
6977  assert(var->scip == set->scip);
6978 
6979  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
6980  * of the domain within feastol
6981  */
6982  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6983 
6984  /* adjust bound to integral value if variable is of integral type */
6985  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
6986 
6987  /* check that the adjusted bound is feasible
6988  * @todo this does not have to be the case if the original problem was infeasible due to bounds and we are called
6989  * here because we reset bounds to their original value!
6990  */
6991  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->glbdom.lb));
6992 
6993  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
6994  {
6995  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
6996  newbound = MAX(newbound, var->glbdom.lb);
6997  }
6998  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
6999 
7000  /* the new global bound has to be tighter except we are in the original problem; this must be w.r.t. feastol because
7001  * SCIPvarFix() allows fixings that are outside of the domain within feastol
7002  */
7003  assert(lp == NULL || SCIPsetIsFeasGE(set, var->glbdom.ub, newbound) || (set->reopt_enable && set->stage == SCIP_STAGE_PRESOLVED));
7004 
7005  SCIPsetDebugMsg(set, "changing global upper bound of <%s> from %g to %g\n", var->name, var->glbdom.ub, newbound);
7006 
7007  if( SCIPsetIsEQ(set, var->glbdom.ub, newbound) )
7008  return SCIP_OKAY;
7009 
7010  /* change bounds of attached variables */
7011  switch( SCIPvarGetStatus(var) )
7012  {
7014  if( var->data.original.transvar != NULL )
7015  {
7016  SCIP_CALL( SCIPvarChgUbGlobal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7017  newbound) );
7018  }
7019  else
7020  {
7021  assert(set->stage == SCIP_STAGE_PROBLEM);
7022  if( newbound < SCIPvarGetUbLocal(var) )
7023  {
7024  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7025  }
7026  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7027  }
7028  break;
7029 
7030  case SCIP_VARSTATUS_COLUMN:
7031  case SCIP_VARSTATUS_LOOSE:
7032  if( newbound < SCIPvarGetUbLocal(var) )
7033  {
7034  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7035  }
7036  SCIP_CALL( varProcessChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound) );
7037  break;
7038 
7039  case SCIP_VARSTATUS_FIXED:
7040  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7041  return SCIP_INVALIDDATA;
7042 
7043  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7044  assert(var->data.aggregate.var != NULL);
7045  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7046  {
7047  SCIP_Real childnewbound;
7048 
7049  /* a > 0 -> change lower bound of y */
7050  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->glbdom.ub))
7051  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7053  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7054  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7055  else
7056  childnewbound = newbound;
7057  SCIP_CALL( SCIPvarChgUbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7058  childnewbound) );
7059  }
7060  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7061  {
7062  SCIP_Real childnewbound;
7063 
7064  /* a < 0 -> change upper bound of y */
7065  assert((SCIPsetIsInfinity(set, var->glbdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->glbdom.lb))
7066  || SCIPsetIsFeasEQ(set, var->glbdom.ub,
7068  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7069  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7070  else
7071  childnewbound = -newbound;
7072  SCIP_CALL( SCIPvarChgLbGlobal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7073  childnewbound) );
7074  }
7075  else
7076  {
7077  SCIPerrorMessage("scalar is zero in aggregation\n");
7078  return SCIP_INVALIDDATA;
7079  }
7080  break;
7081 
7083  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7084  return SCIP_INVALIDDATA;
7085 
7086  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7087  assert(var->negatedvar != NULL);
7089  assert(var->negatedvar->negatedvar == var);
7090  SCIP_CALL( SCIPvarChgLbGlobal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable,
7091  var->data.negate.constant - newbound) );
7092  break;
7093 
7094  default:
7095  SCIPerrorMessage("unknown variable status\n");
7096  return SCIP_INVALIDDATA;
7097  }
7098 
7099  return SCIP_OKAY;
7100 }
7101 
7102 /** changes lazy lower bound of the variable, this is only possible if the variable is not in the LP yet */
7104  SCIP_VAR* var, /**< problem variable */
7105  SCIP_SET* set, /**< global SCIP settings */
7106  SCIP_Real lazylb /**< the lazy lower bound to be set */
7107  )
7108 {
7109  assert(var != NULL);
7110  assert(var->probindex != -1);
7111  assert(SCIPsetIsFeasGE(set, var->glbdom.ub, lazylb));
7112  assert(SCIPsetIsFeasGE(set, var->lazyub, lazylb));
7113  assert(set != NULL);
7114  assert(var->scip == set->scip);
7115 
7116  /* variable should not be in the LP */
7118  return SCIP_INVALIDCALL;
7119 
7120  var->lazylb = lazylb;
7121 
7122  return SCIP_OKAY;
7123 }
7124 
7125 /** changes lazy upper bound of the variable, this is only possible if the variable is not in the LP yet */
7127  SCIP_VAR* var, /**< problem variable */
7128  SCIP_SET* set, /**< global SCIP settings */
7129  SCIP_Real lazyub /**< the lazy lower bound to be set */
7130  )
7131 {
7132  assert(var != NULL);
7133  assert(var->probindex != -1);
7134  assert(SCIPsetIsFeasGE(set, lazyub, var->glbdom.lb));
7135  assert(SCIPsetIsFeasGE(set, lazyub, var->lazylb));
7136  assert(set != NULL);
7137  assert(var->scip == set->scip);
7138 
7139  /* variable should not be in the LP */
7141  return SCIP_INVALIDCALL;
7142 
7143  var->lazyub = lazyub;
7144 
7145  return SCIP_OKAY;
7146 }
7147 
7148 
7149 /** changes global bound of variable; if possible, adjusts bound to integral value;
7150  * updates local bound if the global bound is tighter
7151  */
7153  SCIP_VAR* var, /**< problem variable to change */
7154  BMS_BLKMEM* blkmem, /**< block memory */
7155  SCIP_SET* set, /**< global SCIP settings */
7156  SCIP_STAT* stat, /**< problem statistics */
7157  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7158  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7159  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7160  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
7161  SCIP_Real newbound, /**< new bound for variable */
7162  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7163  )
7164 {
7165  /* apply bound change to the LP data */
7166  switch( boundtype )
7167  {
7168  case SCIP_BOUNDTYPE_LOWER:
7169  return SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7170  case SCIP_BOUNDTYPE_UPPER:
7171  return SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newbound);
7172  default:
7173  SCIPerrorMessage("unknown bound type\n");
7174  return SCIP_INVALIDDATA;
7175  }
7176 }
7177 
7178 /** appends LBTIGHTENED or LBRELAXED event to the event queue */
7179 static
7181  SCIP_VAR* var, /**< problem variable to change */
7182  BMS_BLKMEM* blkmem, /**< block memory */
7183  SCIP_SET* set, /**< global SCIP settings */
7184  SCIP_LP* lp, /**< current LP data */
7185  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7186  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7187  SCIP_Real oldbound, /**< old lower bound for variable */
7188  SCIP_Real newbound /**< new lower bound for variable */
7189  )
7190 {
7191  assert(var != NULL);
7192  assert(var->eventfilter != NULL);
7193  assert(SCIPvarIsTransformed(var));
7194  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.lb); /*lint !e777*/
7195  assert(set != NULL);
7196  assert(var->scip == set->scip);
7197 
7198  /* check, if the variable is being tracked for bound changes
7199  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7200  */
7201  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_LBCHANGED) != 0)
7204  {
7205  SCIP_EVENT* event;
7206 
7207  SCIPsetDebugMsg(set, "issue LBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7208 
7209  SCIP_CALL( SCIPeventCreateLbChanged(&event, blkmem, var, oldbound, newbound) );
7210  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7211  }
7212 
7213  return SCIP_OKAY;
7214 }
7215 
7216 /** appends UBTIGHTENED or UBRELAXED event to the event queue */
7217 static
7219  SCIP_VAR* var, /**< problem variable to change */
7220  BMS_BLKMEM* blkmem, /**< block memory */
7221  SCIP_SET* set, /**< global SCIP settings */
7222  SCIP_LP* lp, /**< current LP data */
7223  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
7224  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
7225  SCIP_Real oldbound, /**< old upper bound for variable */
7226  SCIP_Real newbound /**< new upper bound for variable */
7227  )
7228 {
7229  assert(var != NULL);
7230  assert(var->eventfilter != NULL);
7231  assert(SCIPvarIsTransformed(var));
7232  assert(!SCIPsetIsEQ(set, oldbound, newbound) || newbound == var->glbdom.ub); /*lint !e777*/
7233  assert(set != NULL);
7234  assert(var->scip == set->scip);
7235 
7236  /* check, if the variable is being tracked for bound changes
7237  * COLUMN and LOOSE variables are tracked always, because row activities and LP changes have to be updated
7238  */
7239  if( (var->eventfilter->len > 0 && (var->eventfilter->eventmask & SCIP_EVENTTYPE_UBCHANGED) != 0)
7242  {
7243  SCIP_EVENT* event;
7244 
7245  SCIPsetDebugMsg(set, "issue UBCHANGED event for variable <%s>: %g -> %g\n", var->name, oldbound, newbound);
7246 
7247  SCIP_CALL( SCIPeventCreateUbChanged(&event, blkmem, var, oldbound, newbound) );
7248  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, lp, branchcand, NULL, &event) );
7249  }
7250 
7251  return SCIP_OKAY;
7252 }
7253 
7254 /* forward declaration, because both methods call each other recursively */
7255 
7256 /* performs the current change in upper bound, changes all parents accordingly */
7257 static
7259  SCIP_VAR* var, /**< problem variable to change */
7260  BMS_BLKMEM* blkmem, /**< block memory */
7261  SCIP_SET* set, /**< global SCIP settings */
7262  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7263  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7264  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7265  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7266  SCIP_Real newbound /**< new bound for variable */
7267  );
7268 
7269 /** performs the current change in lower bound, changes all parents accordingly */
7270 static
7272  SCIP_VAR* var, /**< problem variable to change */
7273  BMS_BLKMEM* blkmem, /**< block memory */
7274  SCIP_SET* set, /**< global SCIP settings */
7275  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7276  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7277  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7278  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7279  SCIP_Real newbound /**< new bound for variable */
7280  )
7281 {
7282  SCIP_VAR* parentvar;
7283  SCIP_Real oldbound;
7284  int i;
7285 
7286  assert(var != NULL);
7287  assert(set != NULL);
7288  assert(var->scip == set->scip);
7289  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7290  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7291  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7292  || SCIPsetIsEQ(set, newbound, var->locdom.ub)))
7294 
7295  /* check that the bound is feasible */
7296  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsLE(set, newbound, var->glbdom.ub));
7297  /* adjust bound to integral value if variable is of integral type */
7298  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7299 
7300  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7301  {
7302  /* we do not want to exceed the upper bound, which could have happened due to numerics */
7303  newbound = MIN(newbound, var->locdom.ub);
7304 
7305  /* we do not want to undercut the global lower bound, which could have happened due to numerics */
7306  newbound = MAX(newbound, var->glbdom.lb);
7307  }
7308  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7309 
7310  SCIPsetDebugMsg(set, "process changing lower bound of <%s> from %g to %g\n", var->name, var->locdom.lb, newbound);
7311 
7312  if( SCIPsetIsEQ(set, newbound, var->glbdom.lb) && var->glbdom.lb != var->locdom.lb ) /*lint !e777*/
7313  newbound = var->glbdom.lb;
7314  else if( SCIPsetIsEQ(set, newbound, var->locdom.lb) )
7315  return SCIP_OKAY;
7316 
7317  /* change the bound */
7318  oldbound = var->locdom.lb;
7319  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasLE(set, newbound, var->locdom.ub));
7320  var->locdom.lb = newbound;
7321 
7322  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7323  * once update the statistic
7324  */
7325  if( stat != NULL )
7326  SCIPstatIncrement(stat, set, domchgcount);
7327 
7328  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7329  {
7330  /* merges overlapping holes into single holes, moves bounds respectively */
7331  domMerge(&var->locdom, blkmem, set, &newbound, NULL);
7332  }
7333 
7334  /* issue bound change event */
7335  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7336  if( var->eventfilter != NULL )
7337  {
7338  SCIP_CALL( varEventLbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7339  }
7340 
7341  /* process parent variables */
7342  for( i = 0; i < var->nparentvars; ++i )
7343  {
7344  parentvar = var->parentvars[i];
7345  assert(parentvar != NULL);
7346 
7347  switch( SCIPvarGetStatus(parentvar) )
7348  {
7350  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7351  break;
7352 
7353  case SCIP_VARSTATUS_COLUMN:
7354  case SCIP_VARSTATUS_LOOSE:
7355  case SCIP_VARSTATUS_FIXED:
7357  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7358  return SCIP_INVALIDDATA;
7359 
7360  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7361  assert(parentvar->data.aggregate.var == var);
7362  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7363  {
7364  SCIP_Real parentnewbound;
7365 
7366  /* a > 0 -> change lower bound of y */
7367  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, -oldbound))
7368  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7369  || (SCIPsetIsZero(set, parentvar->locdom.lb / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7370 
7371  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7372  {
7373  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7374  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7375  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7376  * as a result, the parent's lower bound is set to it's upper bound, and not above
7377  */
7378  if( parentnewbound > parentvar->glbdom.ub )
7379  {
7380  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7381  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7382  parentnewbound = parentvar->glbdom.ub;
7383  }
7384  }
7385  else
7386  parentnewbound = newbound;
7387  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7388  }
7389  else
7390  {
7391  SCIP_Real parentnewbound;
7392 
7393  /* a < 0 -> change upper bound of y */
7394  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7395  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, -oldbound))
7396  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub, oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant)
7397  || (SCIPsetIsZero(set, parentvar->locdom.ub / parentvar->data.aggregate.scalar) && SCIPsetIsZero(set, oldbound)));
7398 
7399  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7400  {
7401  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7402  /* if parent's new upper bound is below its lower bound, then this could be due to numerical difficulties, e.g., if numbers are large
7403  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7404  * as a result, the parent's upper bound is set to it's lower bound, and not below
7405  */
7406  if( parentnewbound < parentvar->glbdom.lb )
7407  {
7408  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7409  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7410  parentnewbound = parentvar->glbdom.lb;
7411  }
7412  }
7413  else
7414  parentnewbound = -newbound;
7415  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7416  }
7417  break;
7418 
7419  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7420  assert(parentvar->negatedvar != NULL);
7421  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7422  assert(parentvar->negatedvar->negatedvar == parentvar);
7423  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7424  parentvar->data.negate.constant - newbound) );
7425  break;
7426 
7427  default:
7428  SCIPerrorMessage("unknown variable status\n");
7429  return SCIP_INVALIDDATA;
7430  }
7431  }
7432 
7433  return SCIP_OKAY;
7434 }
7435 
7436 /** performs the current change in upper bound, changes all parents accordingly */
7437 static
7439  SCIP_VAR* var, /**< problem variable to change */
7440  BMS_BLKMEM* blkmem, /**< block memory */
7441  SCIP_SET* set, /**< global SCIP settings */
7442  SCIP_STAT* stat, /**< problem statistics, or NULL if the bound change belongs to updating the parent variables */
7443  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7444  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7445  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7446  SCIP_Real newbound /**< new bound for variable */
7447  )
7448 {
7449  SCIP_VAR* parentvar;
7450  SCIP_Real oldbound;
7451  int i;
7452 
7453  assert(var != NULL);
7454  assert(set != NULL);
7455  assert(var->scip == set->scip);
7456  assert((SCIPvarGetType(var) == SCIP_VARTYPE_BINARY && (SCIPsetIsZero(set, newbound) || SCIPsetIsEQ(set, newbound, 1.0)
7457  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7458  || (SCIPvarGetType(var) < SCIP_VARTYPE_CONTINUOUS && (SCIPsetIsIntegral(set, newbound)
7459  || SCIPsetIsEQ(set, newbound, var->locdom.lb)))
7461 
7462  /* check that the bound is feasible */
7463  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsGE(set, newbound, var->glbdom.lb));
7464  /* adjust bound to integral value if variable is of integral type */
7465  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7466 
7467  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7468  {
7469  /* we do not want to undercut the lower bound, which could have happened due to numerics */
7470  newbound = MAX(newbound, var->locdom.lb);
7471 
7472  /* we do not want to exceed the global upper bound, which could have happened due to numerics */
7473  newbound = MIN(newbound, var->glbdom.ub);
7474  }
7475  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7476 
7477  SCIPsetDebugMsg(set, "process changing upper bound of <%s> from %g to %g\n", var->name, var->locdom.ub, newbound);
7478 
7479  if( SCIPsetIsEQ(set, newbound, var->glbdom.ub) && var->glbdom.ub != var->locdom.ub ) /*lint !e777*/
7480  newbound = var->glbdom.ub;
7481  else if( SCIPsetIsEQ(set, newbound, var->locdom.ub) )
7482  return SCIP_OKAY;
7483 
7484  /* change the bound */
7485  oldbound = var->locdom.ub;
7486  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || SCIPsetIsFeasGE(set, newbound, var->locdom.lb));
7487  var->locdom.ub = newbound;
7488 
7489  /* update statistic; during the update steps of the parent variable we pass a NULL pointer to ensure that we only
7490  * once update the statistic
7491  */
7492  if( stat != NULL )
7493  SCIPstatIncrement(stat, set, domchgcount);
7494 
7495  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7496  {
7497  /* merges overlapping holes into single holes, moves bounds respectively */
7498  domMerge(&var->locdom, blkmem, set, NULL, &newbound);
7499  }
7500 
7501  /* issue bound change event */
7502  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
7503  if( var->eventfilter != NULL )
7504  {
7505  SCIP_CALL( varEventUbChanged(var, blkmem, set, lp, branchcand, eventqueue, oldbound, newbound) );
7506  }
7507 
7508  /* process parent variables */
7509  for( i = 0; i < var->nparentvars; ++i )
7510  {
7511  parentvar = var->parentvars[i];
7512  assert(parentvar != NULL);
7513 
7514  switch( SCIPvarGetStatus(parentvar) )
7515  {
7517  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, newbound) );
7518  break;
7519 
7520  case SCIP_VARSTATUS_COLUMN:
7521  case SCIP_VARSTATUS_LOOSE:
7522  case SCIP_VARSTATUS_FIXED:
7524  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
7525  return SCIP_INVALIDDATA;
7526 
7527  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7528  assert(parentvar->data.aggregate.var == var);
7529  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
7530  {
7531  SCIP_Real parentnewbound;
7532 
7533  /* a > 0 -> change upper bound of x */
7534  assert((SCIPsetIsInfinity(set, parentvar->locdom.ub) && SCIPsetIsInfinity(set, oldbound))
7535  || SCIPsetIsFeasEQ(set, parentvar->locdom.ub,
7536  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7537  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7538  {
7539  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7540  /* 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
7541  * thus, at least a relative comparision of the new upper bound and the current lower bound should proof consistency
7542  * as a result, the parent's upper bound is set to it's lower bound, and not below
7543  */
7544  if( parentnewbound < parentvar->glbdom.lb )
7545  {
7546  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7547  assert(SCIPsetIsFeasGE(set, parentnewbound, parentvar->glbdom.lb));
7548  parentnewbound = parentvar->glbdom.lb;
7549  }
7550  }
7551  else
7552  parentnewbound = newbound;
7553  SCIP_CALL( varProcessChgUbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7554  }
7555  else
7556  {
7557  SCIP_Real parentnewbound;
7558 
7559  /* a < 0 -> change lower bound of x */
7560  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
7561  assert((SCIPsetIsInfinity(set, -parentvar->locdom.lb) && SCIPsetIsInfinity(set, oldbound))
7562  || SCIPsetIsFeasEQ(set, parentvar->locdom.lb,
7563  oldbound * parentvar->data.aggregate.scalar + parentvar->data.aggregate.constant));
7564  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7565  {
7566  parentnewbound = parentvar->data.aggregate.scalar * newbound + parentvar->data.aggregate.constant;
7567  /* if parent's new lower bound exceeds its upper bound, then this could be due to numerical difficulties, e.g., if numbers are large
7568  * thus, at least a relative comparision of the new lower bound and the current upper bound should proof consistency
7569  * as a result, the parent's lower bound is set to it's upper bound, and not above
7570  */
7571  if( parentnewbound > parentvar->glbdom.ub )
7572  {
7573  /* due to numerics we only need to be feasible w.r.t. feasibility tolerance */
7574  assert(SCIPsetIsFeasLE(set, parentnewbound, parentvar->glbdom.ub));
7575  parentnewbound = parentvar->glbdom.ub;
7576  }
7577  }
7578  else
7579  parentnewbound = -newbound;
7580  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue, parentnewbound) );
7581  }
7582  break;
7583 
7584  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
7585  assert(parentvar->negatedvar != NULL);
7586  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
7587  assert(parentvar->negatedvar->negatedvar == parentvar);
7588  SCIP_CALL( varProcessChgLbLocal(parentvar, blkmem, set, NULL, lp, branchcand, eventqueue,
7589  parentvar->data.negate.constant - newbound) );
7590  break;
7591 
7592  default:
7593  SCIPerrorMessage("unknown variable status\n");
7594  return SCIP_INVALIDDATA;
7595  }
7596  }
7597 
7598  return SCIP_OKAY;
7599 }
7600 
7601 /** changes current local lower bound of variable; if possible, adjusts bound to integral value; stores inference
7602  * information in variable
7603  */
7605  SCIP_VAR* var, /**< problem variable to change */
7606  BMS_BLKMEM* blkmem, /**< block memory */
7607  SCIP_SET* set, /**< global SCIP settings */
7608  SCIP_STAT* stat, /**< problem statistics */
7609  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7610  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7611  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7612  SCIP_Real newbound /**< new bound for variable */
7613  )
7614 {
7615  assert(var != NULL);
7616  assert(blkmem != NULL);
7617  assert(set != NULL);
7618  assert(var->scip == set->scip);
7619 
7620  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7621  * of the domain within feastol
7622  */
7623  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7624 
7625  /* adjust bound to integral value if variable is of integral type */
7626  newbound = adjustedLb(set, SCIPvarGetType(var), newbound);
7627 
7628  /* check that the adjusted bound is feasible */
7629  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasGT(set, newbound, var->locdom.ub));
7630 
7631  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7632  {
7633  /* we do not want to exceed the upperbound, which could have happened due to numerics */
7634  newbound = MIN(newbound, var->locdom.ub);
7635  }
7636  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7637 
7638  SCIPsetDebugMsg(set, "changing lower bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7639 
7640  if( SCIPsetIsEQ(set, var->locdom.lb, newbound) && (!SCIPsetIsEQ(set, var->glbdom.lb, newbound) || var->locdom.lb == newbound) ) /*lint !e777*/
7641  return SCIP_OKAY;
7642 
7643  /* change bounds of attached variables */
7644  switch( SCIPvarGetStatus(var) )
7645  {
7647  if( var->data.original.transvar != NULL )
7648  {
7649  SCIP_CALL( SCIPvarChgLbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue,
7650  newbound) );
7651  }
7652  else
7653  {
7654  assert(set->stage == SCIP_STAGE_PROBLEM);
7655  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7656  }
7657  break;
7658 
7659  case SCIP_VARSTATUS_COLUMN:
7660  case SCIP_VARSTATUS_LOOSE:
7661  SCIP_CALL( varProcessChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7662  break;
7663 
7664  case SCIP_VARSTATUS_FIXED:
7665  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7666  return SCIP_INVALIDDATA;
7667 
7668  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7669  assert(var->data.aggregate.var != NULL);
7670  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7671  {
7672  SCIP_Real childnewbound;
7673 
7674  /* a > 0 -> change lower bound of y */
7675  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7676  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7678  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7679  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7680  else
7681  childnewbound = newbound;
7682  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7683  childnewbound) );
7684  }
7685  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7686  {
7687  SCIP_Real childnewbound;
7688 
7689  /* a < 0 -> change upper bound of y */
7690  assert((SCIPsetIsInfinity(set, -var->locdom.lb) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7691  || SCIPsetIsFeasEQ(set, var->locdom.lb,
7693  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7694  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7695  else
7696  childnewbound = -newbound;
7697  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7698  childnewbound) );
7699  }
7700  else
7701  {
7702  SCIPerrorMessage("scalar is zero in aggregation\n");
7703  return SCIP_INVALIDDATA;
7704  }
7705  break;
7706 
7708  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7709  return SCIP_INVALIDDATA;
7710 
7711  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7712  assert(var->negatedvar != NULL);
7714  assert(var->negatedvar->negatedvar == var);
7715  SCIP_CALL( SCIPvarChgUbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7716  var->data.negate.constant - newbound) );
7717  break;
7718 
7719  default:
7720  SCIPerrorMessage("unknown variable status\n");
7721  return SCIP_INVALIDDATA;
7722  }
7723 
7724  return SCIP_OKAY;
7725 }
7726 
7727 /** changes current local upper bound of variable; if possible, adjusts bound to integral value; stores inference
7728  * information in variable
7729  */
7731  SCIP_VAR* var, /**< problem variable to change */
7732  BMS_BLKMEM* blkmem, /**< block memory */
7733  SCIP_SET* set, /**< global SCIP settings */
7734  SCIP_STAT* stat, /**< problem statistics */
7735  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7736  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7737  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7738  SCIP_Real newbound /**< new bound for variable */
7739  )
7740 {
7741  assert(var != NULL);
7742  assert(blkmem != NULL);
7743  assert(set != NULL);
7744  assert(var->scip == set->scip);
7745 
7746  /* check that the bound is feasible; this must be w.r.t. feastol because SCIPvarFix() allows fixings that are outside
7747  * of the domain within feastol
7748  */
7749  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7750 
7751  /* adjust bound to integral value if variable is of integral type */
7752  newbound = adjustedUb(set, SCIPvarGetType(var), newbound);
7753 
7754  /* check that the adjusted bound is feasible */
7755  assert(SCIPsetGetStage(set) == SCIP_STAGE_PROBLEM || !SCIPsetIsFeasLT(set, newbound, var->locdom.lb));
7756 
7757  if( SCIPsetGetStage(set) != SCIP_STAGE_PROBLEM )
7758  {
7759  /* we do not want to undercut the lowerbound, which could have happened due to numerics */
7760  newbound = MAX(newbound, var->locdom.lb);
7761  }
7762  assert(SCIPvarGetType(var) == SCIP_VARTYPE_CONTINUOUS || SCIPsetIsFeasIntegral(set, newbound));
7763 
7764  SCIPsetDebugMsg(set, "changing upper bound of <%s>[%g,%g] to %g\n", var->name, var->locdom.lb, var->locdom.ub, newbound);
7765 
7766  if( SCIPsetIsEQ(set, var->locdom.ub, newbound) && (!SCIPsetIsEQ(set, var->glbdom.ub, newbound) || var->locdom.ub == newbound) ) /*lint !e777*/
7767  return SCIP_OKAY;
7768 
7769  /* change bounds of attached variables */
7770  switch( SCIPvarGetStatus(var) )
7771  {
7773  if( var->data.original.transvar != NULL )
7774  {
7775  SCIP_CALL( SCIPvarChgUbLocal(var->data.original.transvar, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7776  }
7777  else
7778  {
7779  assert(set->stage == SCIP_STAGE_PROBLEM);
7780  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7781  }
7782  break;
7783 
7784  case SCIP_VARSTATUS_COLUMN:
7785  case SCIP_VARSTATUS_LOOSE:
7786  SCIP_CALL( varProcessChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound) );
7787  break;
7788 
7789  case SCIP_VARSTATUS_FIXED:
7790  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7791  return SCIP_INVALIDDATA;
7792 
7793  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7794  assert(var->data.aggregate.var != NULL);
7795  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7796  {
7797  SCIP_Real childnewbound;
7798 
7799  /* a > 0 -> change upper bound of y */
7800  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, var->data.aggregate.var->locdom.ub))
7801  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7803  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7804  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7805  else
7806  childnewbound = newbound;
7807  SCIP_CALL( SCIPvarChgUbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7808  childnewbound) );
7809  }
7810  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7811  {
7812  SCIP_Real childnewbound;
7813 
7814  /* a < 0 -> change lower bound of y */
7815  assert((SCIPsetIsInfinity(set, var->locdom.ub) && SCIPsetIsInfinity(set, -var->data.aggregate.var->locdom.lb))
7816  || SCIPsetIsFeasEQ(set, var->locdom.ub,
7818  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7819  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7820  else
7821  childnewbound = -newbound;
7822  SCIP_CALL( SCIPvarChgLbLocal(var->data.aggregate.var, blkmem, set, stat, lp, branchcand, eventqueue,
7823  childnewbound) );
7824  }
7825  else
7826  {
7827  SCIPerrorMessage("scalar is zero in aggregation\n");
7828  return SCIP_INVALIDDATA;
7829  }
7830  break;
7831 
7833  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7834  return SCIP_INVALIDDATA;
7835 
7836  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7837  assert(var->negatedvar != NULL);
7839  assert(var->negatedvar->negatedvar == var);
7840  SCIP_CALL( SCIPvarChgLbLocal(var->negatedvar, blkmem, set, stat, lp, branchcand, eventqueue,
7841  var->data.negate.constant - newbound) );
7842  break;
7843 
7844  default:
7845  SCIPerrorMessage("unknown variable status\n");
7846  return SCIP_INVALIDDATA;
7847  }
7848 
7849  return SCIP_OKAY;
7850 }
7851 
7852 /** changes current local bound of variable; if possible, adjusts bound to integral value; stores inference
7853  * information in variable
7854  */
7856  SCIP_VAR* var, /**< problem variable to change */
7857  BMS_BLKMEM* blkmem, /**< block memory */
7858  SCIP_SET* set, /**< global SCIP settings */
7859  SCIP_STAT* stat, /**< problem statistics */
7860  SCIP_LP* lp, /**< current LP data, may be NULL for original variables */
7861  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage, may be NULL for original variables */
7862  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
7863  SCIP_Real newbound, /**< new bound for variable */
7864  SCIP_BOUNDTYPE boundtype /**< type of bound: lower or upper bound */
7865  )
7866 {
7867  /* apply bound change to the LP data */
7868  switch( boundtype )
7869  {
7870  case SCIP_BOUNDTYPE_LOWER:
7871  return SCIPvarChgLbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7872  case SCIP_BOUNDTYPE_UPPER:
7873  return SCIPvarChgUbLocal(var, blkmem, set, stat, lp, branchcand, eventqueue, newbound);
7874  default:
7875  SCIPerrorMessage("unknown bound type\n");
7876  return SCIP_INVALIDDATA;
7877  }
7878 }
7879 
7880 /** changes lower bound of variable in current dive; if possible, adjusts bound to integral value */
7882  SCIP_VAR* var, /**< problem variable to change */
7883  SCIP_SET* set, /**< global SCIP settings */
7884  SCIP_LP* lp, /**< current LP data */
7885  SCIP_Real newbound /**< new bound for variable */
7886  )
7887 {
7888  assert(var != NULL);
7889  assert(set != NULL);
7890  assert(var->scip == set->scip);
7891  assert(lp != NULL);
7892  assert(SCIPlpDiving(lp));
7893 
7894  /* adjust bound for integral variables */
7895  SCIPvarAdjustLb(var, set, &newbound);
7896 
7897  SCIPsetDebugMsg(set, "changing lower bound of <%s> to %g in current dive\n", var->name, newbound);
7898 
7899  /* change bounds of attached variables */
7900  switch( SCIPvarGetStatus(var) )
7901  {
7903  assert(var->data.original.transvar != NULL);
7904  SCIP_CALL( SCIPvarChgLbDive(var->data.original.transvar, set, lp, newbound) );
7905  break;
7906 
7907  case SCIP_VARSTATUS_COLUMN:
7908  assert(var->data.col != NULL);
7909  SCIP_CALL( SCIPcolChgLb(var->data.col, set, lp, newbound) );
7910  break;
7911 
7912  case SCIP_VARSTATUS_LOOSE:
7913  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
7914  return SCIP_INVALIDDATA;
7915 
7916  case SCIP_VARSTATUS_FIXED:
7917  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
7918  return SCIP_INVALIDDATA;
7919 
7920  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
7921  assert(var->data.aggregate.var != NULL);
7922  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
7923  {
7924  SCIP_Real childnewbound;
7925 
7926  /* a > 0 -> change lower bound of y */
7927  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7928  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7929  else
7930  childnewbound = newbound;
7931  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
7932  }
7933  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
7934  {
7935  SCIP_Real childnewbound;
7936 
7937  /* a < 0 -> change upper bound of y */
7938  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
7939  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
7940  else
7941  childnewbound = -newbound;
7942  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
7943  }
7944  else
7945  {
7946  SCIPerrorMessage("scalar is zero in aggregation\n");
7947  return SCIP_INVALIDDATA;
7948  }
7949  break;
7950 
7952  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
7953  return SCIP_INVALIDDATA;
7954 
7955  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
7956  assert(var->negatedvar != NULL);
7958  assert(var->negatedvar->negatedvar == var);
7959  SCIP_CALL( SCIPvarChgUbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
7960  break;
7961 
7962  default:
7963  SCIPerrorMessage("unknown variable status\n");
7964  return SCIP_INVALIDDATA;
7965  }
7966 
7967  return SCIP_OKAY;
7968 }
7969 
7970 /** changes upper bound of variable in current dive; if possible, adjusts bound to integral value */
7972  SCIP_VAR* var, /**< problem variable to change */
7973  SCIP_SET* set, /**< global SCIP settings */
7974  SCIP_LP* lp, /**< current LP data */
7975  SCIP_Real newbound /**< new bound for variable */
7976  )
7977 {
7978  assert(var != NULL);
7979  assert(set != NULL);
7980  assert(var->scip == set->scip);
7981  assert(lp != NULL);
7982  assert(SCIPlpDiving(lp));
7983 
7984  /* adjust bound for integral variables */
7985  SCIPvarAdjustUb(var, set, &newbound);
7986 
7987  SCIPsetDebugMsg(set, "changing upper bound of <%s> to %g in current dive\n", var->name, newbound);
7988 
7989  /* change bounds of attached variables */
7990  switch( SCIPvarGetStatus(var) )
7991  {
7993  assert(var->data.original.transvar != NULL);
7994  SCIP_CALL( SCIPvarChgUbDive(var->data.original.transvar, set, lp, newbound) );
7995  break;
7996 
7997  case SCIP_VARSTATUS_COLUMN:
7998  assert(var->data.col != NULL);
7999  SCIP_CALL( SCIPcolChgUb(var->data.col, set, lp, newbound) );
8000  break;
8001 
8002  case SCIP_VARSTATUS_LOOSE:
8003  SCIPerrorMessage("cannot change variable's bounds in dive for LOOSE variables\n");
8004  return SCIP_INVALIDDATA;
8005 
8006  case SCIP_VARSTATUS_FIXED:
8007  SCIPerrorMessage("cannot change the bounds of a fixed variable\n");
8008  return SCIP_INVALIDDATA;
8009 
8010  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8011  assert(var->data.aggregate.var != NULL);
8012  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8013  {
8014  SCIP_Real childnewbound;
8015 
8016  /* a > 0 -> change upper bound of y */
8017  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8018  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8019  else
8020  childnewbound = newbound;
8021  SCIP_CALL( SCIPvarChgUbDive(var->data.aggregate.var, set, lp, childnewbound) );
8022  }
8023  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8024  {
8025  SCIP_Real childnewbound;
8026 
8027  /* a < 0 -> change lower bound of y */
8028  if( !SCIPsetIsInfinity(set, -newbound) && !SCIPsetIsInfinity(set, newbound) )
8029  childnewbound = (newbound - var->data.aggregate.constant)/var->data.aggregate.scalar;
8030  else
8031  childnewbound = -newbound;
8032  SCIP_CALL( SCIPvarChgLbDive(var->data.aggregate.var, set, lp, childnewbound) );
8033  }
8034  else
8035  {
8036  SCIPerrorMessage("scalar is zero in aggregation\n");
8037  return SCIP_INVALIDDATA;
8038  }
8039  break;
8040 
8042  SCIPerrorMessage("cannot change the bounds of a multi-aggregated variable.\n");
8043  return SCIP_INVALIDDATA;
8044 
8045  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8046  assert(var->negatedvar != NULL);
8048  assert(var->negatedvar->negatedvar == var);
8049  SCIP_CALL( SCIPvarChgLbDive(var->negatedvar, set, lp, var->data.negate.constant - newbound) );
8050  break;
8051 
8052  default:
8053  SCIPerrorMessage("unknown variable status\n");
8054  return SCIP_INVALIDDATA;
8055  }
8056 
8057  return SCIP_OKAY;
8058 }
8059 
8060 /** for a multi-aggregated variable, gives the local lower bound computed by adding the local bounds from all
8061  * aggregation variables, this lower bound may be tighter than the one given by SCIPvarGetLbLocal, since the latter is
8062  * not updated if bounds of aggregation variables are changing
8063  *
8064  * calling this function for a non-multi-aggregated variable is not allowed
8065  */
8067  SCIP_VAR* var, /**< problem variable */
8068  SCIP_SET* set /**< global SCIP settings */
8069  )
8070 {
8071  int i;
8072  SCIP_Real lb;
8073  SCIP_Real bnd;
8074  SCIP_VAR* aggrvar;
8075  SCIP_Bool posinf;
8076  SCIP_Bool neginf;
8077 
8078  assert(var != NULL);
8079  assert(set != NULL);
8080  assert(var->scip == set->scip);
8082 
8083  posinf = FALSE;
8084  neginf = FALSE;
8085  lb = var->data.multaggr.constant;
8086  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8087  {
8088  aggrvar = var->data.multaggr.vars[i];
8089  if( var->data.multaggr.scalars[i] > 0.0 )
8090  {
8091  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8092 
8093  if( SCIPsetIsInfinity(set, bnd) )
8094  posinf = TRUE;
8095  else if( SCIPsetIsInfinity(set, -bnd) )
8096  neginf = TRUE;
8097  else
8098  lb += var->data.multaggr.scalars[i] * bnd;
8099  }
8100  else
8101  {
8102  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8103 
8104  if( SCIPsetIsInfinity(set, -bnd) )
8105  posinf = TRUE;
8106  else if( SCIPsetIsInfinity(set, bnd) )
8107  neginf = TRUE;
8108  else
8109  lb += var->data.multaggr.scalars[i] * bnd;
8110  }
8111 
8112  /* stop if two diffrent infinities (or a -infinity) were found and return local lower bound of multi aggregated
8113  * variable
8114  */
8115  if( neginf )
8116  return SCIPvarGetLbLocal(var);
8117  }
8118 
8119  /* if positive infinity flag was set to true return infinity */
8120  if( posinf )
8121  return SCIPsetInfinity(set);
8122 
8123  return (MAX(lb, SCIPvarGetLbLocal(var))); /*lint !e666*/
8124 }
8125 
8126 /** for a multi-aggregated variable, gives the local upper bound computed by adding the local bounds from all
8127  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbLocal, since the latter is
8128  * not updated if bounds of aggregation variables are changing
8129  *
8130  * calling this function for a non-multi-aggregated variable is not allowed
8131  */
8133  SCIP_VAR* var, /**< problem variable */
8134  SCIP_SET* set /**< global SCIP settings */
8135  )
8136 {
8137  int i;
8138  SCIP_Real ub;
8139  SCIP_Real bnd;
8140  SCIP_VAR* aggrvar;
8141  SCIP_Bool posinf;
8142  SCIP_Bool neginf;
8143 
8144  assert(var != NULL);
8145  assert(set != NULL);
8146  assert(var->scip == set->scip);
8148 
8149  posinf = FALSE;
8150  neginf = FALSE;
8151  ub = var->data.multaggr.constant;
8152  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8153  {
8154  aggrvar = var->data.multaggr.vars[i];
8155  if( var->data.multaggr.scalars[i] > 0.0 )
8156  {
8157  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbLocal(aggrvar, set) : SCIPvarGetUbLocal(aggrvar);
8158 
8159  if( SCIPsetIsInfinity(set, bnd) )
8160  posinf = TRUE;
8161  else if( SCIPsetIsInfinity(set, -bnd) )
8162  neginf = TRUE;
8163  else
8164  ub += var->data.multaggr.scalars[i] * bnd;
8165  }
8166  else
8167  {
8168  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbLocal(aggrvar, set) : SCIPvarGetLbLocal(aggrvar);
8169 
8170  if( SCIPsetIsInfinity(set, -bnd) )
8171  posinf = TRUE;
8172  else if( SCIPsetIsInfinity(set, bnd) )
8173  neginf = TRUE;
8174  else
8175  ub += var->data.multaggr.scalars[i] * bnd;
8176  }
8177 
8178  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8179  * variable
8180  */
8181  if( posinf )
8182  return SCIPvarGetUbLocal(var);
8183  }
8184 
8185  /* if negative infinity flag was set to true return -infinity */
8186  if( neginf )
8187  return -SCIPsetInfinity(set);
8188 
8189  return (MIN(ub, SCIPvarGetUbLocal(var))); /*lint !e666*/
8190 }
8191 
8192 /** for a multi-aggregated variable, gives the global lower bound computed by adding the global bounds from all
8193  * aggregation variables, this global bound may be tighter than the one given by SCIPvarGetLbGlobal, since the latter is
8194  * not updated if bounds of aggregation variables are changing
8195  *
8196  * calling this function for a non-multi-aggregated variable is not allowed
8197  */
8199  SCIP_VAR* var, /**< problem variable */
8200  SCIP_SET* set /**< global SCIP settings */
8201  )
8202 {
8203  int i;
8204  SCIP_Real lb;
8205  SCIP_Real bnd;
8206  SCIP_VAR* aggrvar;
8207  SCIP_Bool posinf;
8208  SCIP_Bool neginf;
8209 
8210  assert(var != NULL);
8211  assert(set != NULL);
8212  assert(var->scip == set->scip);
8214 
8215  posinf = FALSE;
8216  neginf = FALSE;
8217  lb = var->data.multaggr.constant;
8218  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8219  {
8220  aggrvar = var->data.multaggr.vars[i];
8221  if( var->data.multaggr.scalars[i] > 0.0 )
8222  {
8223  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8224 
8225  if( SCIPsetIsInfinity(set, bnd) )
8226  posinf = TRUE;
8227  else if( SCIPsetIsInfinity(set, -bnd) )
8228  neginf = TRUE;
8229  else
8230  lb += var->data.multaggr.scalars[i] * bnd;
8231  }
8232  else
8233  {
8234  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8235 
8236  if( SCIPsetIsInfinity(set, -bnd) )
8237  posinf = TRUE;
8238  else if( SCIPsetIsInfinity(set, bnd) )
8239  neginf = TRUE;
8240  else
8241  lb += var->data.multaggr.scalars[i] * bnd;
8242  }
8243 
8244  /* stop if two diffrent infinities (or a -infinity) were found and return global lower bound of multi aggregated
8245  * variable
8246  */
8247  if( neginf )
8248  return SCIPvarGetLbGlobal(var);
8249  }
8250 
8251  /* if positive infinity flag was set to true return infinity */
8252  if( posinf )
8253  return SCIPsetInfinity(set);
8254 
8255  return (MAX(lb, SCIPvarGetLbGlobal(var))); /*lint !e666*/
8256 }
8257 
8258 /** for a multi-aggregated variable, gives the global upper bound computed by adding the global bounds from all
8259  * aggregation variables, this upper bound may be tighter than the one given by SCIPvarGetUbGlobal, since the latter is
8260  * not updated if bounds of aggregation variables are changing
8261  *
8262  * calling this function for a non-multi-aggregated variable is not allowed
8263  */
8265  SCIP_VAR* var, /**< problem variable */
8266  SCIP_SET* set /**< global SCIP settings */
8267  )
8268 {
8269  int i;
8270  SCIP_Real ub;
8271  SCIP_Real bnd;
8272  SCIP_VAR* aggrvar;
8273  SCIP_Bool posinf;
8274  SCIP_Bool neginf;
8275 
8276  assert(var != NULL);
8277  assert(set != NULL);
8278  assert(var->scip == set->scip);
8280 
8281  posinf = FALSE;
8282  neginf = FALSE;
8283  ub = var->data.multaggr.constant;
8284  for( i = var->data.multaggr.nvars-1 ; i >= 0 ; --i )
8285  {
8286  aggrvar = var->data.multaggr.vars[i];
8287  if( var->data.multaggr.scalars[i] > 0.0 )
8288  {
8289  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrUbGlobal(aggrvar, set) : SCIPvarGetUbGlobal(aggrvar);
8290 
8291  if( SCIPsetIsInfinity(set, bnd) )
8292  posinf = TRUE;
8293  else if( SCIPsetIsInfinity(set, -bnd) )
8294  neginf = TRUE;
8295  else
8296  ub += var->data.multaggr.scalars[i] * bnd;
8297  }
8298  else
8299  {
8300  bnd = SCIPvarGetStatus(aggrvar) == SCIP_VARSTATUS_MULTAGGR ? SCIPvarGetMultaggrLbGlobal(aggrvar, set) : SCIPvarGetLbGlobal(aggrvar);
8301 
8302  if( SCIPsetIsInfinity(set, -bnd) )
8303  posinf = TRUE;
8304  else if( SCIPsetIsInfinity(set, bnd) )
8305  neginf = TRUE;
8306  else
8307  ub += var->data.multaggr.scalars[i] * bnd;
8308  }
8309 
8310  /* stop if two diffrent infinities (or a -infinity) were found and return local upper bound of multi aggregated
8311  * variable
8312  */
8313  if( posinf )
8314  return SCIPvarGetUbGlobal(var);
8315  }
8316 
8317  /* if negative infinity flag was set to true return -infinity */
8318  if( neginf )
8319  return -SCIPsetInfinity(set);
8320 
8321  return (MIN(ub, SCIPvarGetUbGlobal(var))); /*lint !e666*/
8322 }
8323 
8324 /** adds a hole to the original domain of the variable */
8326  SCIP_VAR* var, /**< problem variable */
8327  BMS_BLKMEM* blkmem, /**< block memory */
8328  SCIP_SET* set, /**< global SCIP settings */
8329  SCIP_Real left, /**< left bound of open interval in new hole */
8330  SCIP_Real right /**< right bound of open interval in new hole */
8331  )
8332 {
8333  SCIP_Bool added;
8334 
8335  assert(var != NULL);
8336  assert(!SCIPvarIsTransformed(var));
8338  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8339  assert(set != NULL);
8340  assert(var->scip == set->scip);
8341  assert(set->stage == SCIP_STAGE_PROBLEM);
8342 
8343  SCIPsetDebugMsg(set, "adding original hole (%g,%g) to <%s>\n", left, right, var->name);
8344 
8345  if( SCIPsetIsEQ(set, left, right) )
8346  return SCIP_OKAY;
8347 
8348  /* the interval should not be empty */
8349  assert(SCIPsetIsLT(set, left, right));
8350 
8351  /* the the interval bound should already be adjusted */
8352  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8353  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8354 
8355  /* the the interval should lay between the lower and upper bound */
8356  assert(SCIPsetIsGE(set, left, SCIPvarGetLbOriginal(var)));
8357  assert(SCIPsetIsLE(set, right, SCIPvarGetUbOriginal(var)));
8358 
8359  /* add domain hole */
8360  SCIP_CALL( domAddHole(&var->data.original.origdom, blkmem, set, left, right, &added) );
8361 
8362  /* merges overlapping holes into single holes, moves bounds respectively if hole was added */
8363  if( added )
8364  {
8365  domMerge(&var->data.original.origdom, blkmem, set, NULL, NULL);
8366  }
8367 
8368  /**@todo add hole in parent and child variables (just like with bound changes);
8369  * warning! original vars' holes are in original blkmem, transformed vars' holes in transformed blkmem
8370  */
8371 
8372  return SCIP_OKAY;
8373 }
8374 
8375 /** performs the current add of domain, changes all parents accordingly */
8376 static
8378  SCIP_VAR* var, /**< problem variable */
8379  BMS_BLKMEM* blkmem, /**< block memory */
8380  SCIP_SET* set, /**< global SCIP settings */
8381  SCIP_STAT* stat, /**< problem statistics */
8382  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8383  SCIP_Real left, /**< left bound of open interval in new hole */
8384  SCIP_Real right, /**< right bound of open interval in new hole */
8385  SCIP_Bool* added /**< pointer to store whether the hole was added */
8386  )
8387 {
8388  SCIP_VAR* parentvar;
8389  SCIP_Real newlb;
8390  SCIP_Real newub;
8391  int i;
8392 
8393  assert(var != NULL);
8394  assert(added != NULL);
8395  assert(blkmem != NULL);
8396 
8397  /* the interval should not be empty */
8398  assert(SCIPsetIsLT(set, left, right));
8399 
8400  /* the interval bound should already be adjusted */
8401  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8402  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8403 
8404  /* the interval should lay between the lower and upper bound */
8405  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8406  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8407 
8408  /* @todo add debugging mechanism for holes when using a debugging solution */
8409 
8410  /* add hole to hole list */
8411  SCIP_CALL( domAddHole(&var->glbdom, blkmem, set, left, right, added) );
8412 
8413  /* check if the hole is redundant */
8414  if( !(*added) )
8415  return SCIP_OKAY;
8416 
8417  /* current bounds */
8418  newlb = var->glbdom.lb;
8419  newub = var->glbdom.ub;
8420 
8421  /* merge domain holes */
8422  domMerge(&var->glbdom, blkmem, set, &newlb, &newub);
8423 
8424  /* the bound should not be changed */
8425  assert(SCIPsetIsEQ(set, newlb, var->glbdom.lb));
8426  assert(SCIPsetIsEQ(set, newub, var->glbdom.ub));
8427 
8428  /* issue bound change event */
8429  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8430  if( var->eventfilter != NULL )
8431  {
8432  SCIP_CALL( varEventGholeAdded(var, blkmem, set, eventqueue, left, right) );
8433  }
8434 
8435  /* process parent variables */
8436  for( i = 0; i < var->nparentvars; ++i )
8437  {
8438  SCIP_Real parentnewleft;
8439  SCIP_Real parentnewright;
8440  SCIP_Bool localadded;
8441 
8442  parentvar = var->parentvars[i];
8443  assert(parentvar != NULL);
8444 
8445  switch( SCIPvarGetStatus(parentvar) )
8446  {
8448  parentnewleft = left;
8449  parentnewright = right;
8450  break;
8451 
8452  case SCIP_VARSTATUS_COLUMN:
8453  case SCIP_VARSTATUS_LOOSE:
8454  case SCIP_VARSTATUS_FIXED:
8456  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8457  return SCIP_INVALIDDATA;
8458 
8459  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8460  assert(parentvar->data.aggregate.var == var);
8461 
8462  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8463  {
8464  /* a > 0 -> change upper bound of x */
8465  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8466  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8467  }
8468  else
8469  {
8470  /* a < 0 -> change lower bound of x */
8471  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8472 
8473  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8474  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8475  }
8476  break;
8477 
8478  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8479  assert(parentvar->negatedvar != NULL);
8480  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8481  assert(parentvar->negatedvar->negatedvar == parentvar);
8482 
8483  parentnewright = -left + parentvar->data.negate.constant;
8484  parentnewleft = -right + parentvar->data.negate.constant;
8485  break;
8486 
8487  default:
8488  SCIPerrorMessage("unknown variable status\n");
8489  return SCIP_INVALIDDATA;
8490  }
8491 
8492  SCIPsetDebugMsg(set, "add global hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8493 
8494  /* perform hole added for parent variable */
8495  assert(blkmem != NULL);
8496  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8497  SCIP_CALL( varProcessAddHoleGlobal(parentvar, blkmem, set, stat, eventqueue,
8498  parentnewleft, parentnewright, &localadded) );
8499  assert(localadded);
8500  }
8501 
8502  return SCIP_OKAY;
8503 }
8504 
8505 /** adds a hole to the variable's global and local domain */
8507  SCIP_VAR* var, /**< problem variable */
8508  BMS_BLKMEM* blkmem, /**< block memory */
8509  SCIP_SET* set, /**< global SCIP settings */
8510  SCIP_STAT* stat, /**< problem statistics */
8511  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8512  SCIP_Real left, /**< left bound of open interval in new hole */
8513  SCIP_Real right, /**< right bound of open interval in new hole */
8514  SCIP_Bool* added /**< pointer to store whether the hole was added */
8515  )
8516 {
8517  SCIP_Real childnewleft;
8518  SCIP_Real childnewright;
8519 
8520  assert(var != NULL);
8521  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8522  assert(blkmem != NULL);
8523  assert(added != NULL);
8524 
8525  SCIPsetDebugMsg(set, "adding global hole (%g,%g) to <%s>\n", left, right, var->name);
8526 
8527  /* the interval should not be empty */
8528  assert(SCIPsetIsLT(set, left, right));
8529 
8530  /* the the interval bound should already be adjusted */
8531  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8532  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8533 
8534  /* the the interval should lay between the lower and upper bound */
8535  assert(SCIPsetIsGE(set, left, SCIPvarGetLbGlobal(var)));
8536  assert(SCIPsetIsLE(set, right, SCIPvarGetUbGlobal(var)));
8537 
8538  /* change bounds of attached variables */
8539  switch( SCIPvarGetStatus(var) )
8540  {
8542  if( var->data.original.transvar != NULL )
8543  {
8544  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8545  left, right, added) );
8546  }
8547  else
8548  {
8549  assert(set->stage == SCIP_STAGE_PROBLEM);
8550 
8551  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8552  if( *added )
8553  {
8554  SCIP_Bool localadded;
8555 
8556  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8557  }
8558  }
8559  break;
8560 
8561  case SCIP_VARSTATUS_COLUMN:
8562  case SCIP_VARSTATUS_LOOSE:
8563  SCIP_CALL( varProcessAddHoleGlobal(var, blkmem, set, stat, eventqueue, left, right, added) );
8564  if( *added )
8565  {
8566  SCIP_Bool localadded;
8567 
8568  SCIP_CALL( SCIPvarAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, &localadded) );
8569  }
8570  break;
8571 
8572  case SCIP_VARSTATUS_FIXED:
8573  SCIPerrorMessage("cannot add hole of a fixed variable\n");
8574  return SCIP_INVALIDDATA;
8575 
8576  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8577  assert(var->data.aggregate.var != NULL);
8578 
8579  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8580  {
8581  /* a > 0 -> change lower bound of y */
8582  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8583  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8584  }
8585  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8586  {
8587  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8588  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8589  }
8590  else
8591  {
8592  SCIPerrorMessage("scalar is zero in aggregation\n");
8593  return SCIP_INVALIDDATA;
8594  }
8595  SCIP_CALL( SCIPvarAddHoleGlobal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8596  childnewleft, childnewright, added) );
8597  break;
8598 
8600  SCIPerrorMessage("cannot add a hole of a multi-aggregated variable.\n");
8601  return SCIP_INVALIDDATA;
8602 
8603  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8604  assert(var->negatedvar != NULL);
8606  assert(var->negatedvar->negatedvar == var);
8607 
8608  childnewright = -left + var->data.negate.constant;
8609  childnewleft = -right + var->data.negate.constant;
8610 
8611  SCIP_CALL( SCIPvarAddHoleGlobal(var->negatedvar, blkmem, set, stat, eventqueue,
8612  childnewleft, childnewright, added) );
8613  break;
8614 
8615  default:
8616  SCIPerrorMessage("unknown variable status\n");
8617  return SCIP_INVALIDDATA;
8618  }
8619 
8620  return SCIP_OKAY;
8621 }
8622 
8623 /** performs the current add of domain, changes all parents accordingly */
8624 static
8626  SCIP_VAR* var, /**< problem variable */
8627  BMS_BLKMEM* blkmem, /**< block memory */
8628  SCIP_SET* set, /**< global SCIP settings */
8629  SCIP_STAT* stat, /**< problem statistics */
8630  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8631  SCIP_Real left, /**< left bound of open interval in new hole */
8632  SCIP_Real right, /**< right bound of open interval in new hole */
8633  SCIP_Bool* added /**< pointer to store whether the hole was added, or NULL */
8634  )
8635 {
8636  SCIP_VAR* parentvar;
8637  SCIP_Real newlb;
8638  SCIP_Real newub;
8639  int i;
8640 
8641  assert(var != NULL);
8642  assert(added != NULL);
8643  assert(blkmem != NULL);
8644 
8645  /* the interval should not be empty */
8646  assert(SCIPsetIsLT(set, left, right));
8647 
8648  /* the the interval bound should already be adjusted */
8649  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8650  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8651 
8652  /* the the interval should lay between the lower and upper bound */
8653  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8654  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8655 
8656  /* add hole to hole list */
8657  SCIP_CALL( domAddHole(&var->locdom, blkmem, set, left, right, added) );
8658 
8659  /* check if the hole is redundant */
8660  if( !(*added) )
8661  return SCIP_OKAY;
8662 
8663  /* current bounds */
8664  newlb = var->locdom.lb;
8665  newub = var->locdom.ub;
8666 
8667  /* merge domain holes */
8668  domMerge(&var->locdom, blkmem, set, &newlb, &newub);
8669 
8670  /* the bound should not be changed */
8671  assert(SCIPsetIsEQ(set, newlb, var->locdom.lb));
8672  assert(SCIPsetIsEQ(set, newub, var->locdom.ub));
8673 
8674 #if 0
8675  /* issue bound change event */
8676  assert(SCIPvarIsTransformed(var) == (var->eventfilter != NULL));
8677  if( var->eventfilter != NULL )
8678  {
8679  SCIP_CALL( varEventLholeAdded(var, blkmem, set, lp, branchcand, eventqueue, left, right) );
8680  }
8681 #endif
8682 
8683  /* process parent variables */
8684  for( i = 0; i < var->nparentvars; ++i )
8685  {
8686  SCIP_Real parentnewleft;
8687  SCIP_Real parentnewright;
8688  SCIP_Bool localadded;
8689 
8690  parentvar = var->parentvars[i];
8691  assert(parentvar != NULL);
8692 
8693  switch( SCIPvarGetStatus(parentvar) )
8694  {
8696  parentnewleft = left;
8697  parentnewright = right;
8698  break;
8699 
8700  case SCIP_VARSTATUS_COLUMN:
8701  case SCIP_VARSTATUS_LOOSE:
8702  case SCIP_VARSTATUS_FIXED:
8704  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
8705  return SCIP_INVALIDDATA;
8706 
8707  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8708  assert(parentvar->data.aggregate.var == var);
8709 
8710  if( SCIPsetIsPositive(set, parentvar->data.aggregate.scalar) )
8711  {
8712  /* a > 0 -> change upper bound of x */
8713  parentnewleft = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8714  parentnewright = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8715  }
8716  else
8717  {
8718  /* a < 0 -> change lower bound of x */
8719  assert(SCIPsetIsNegative(set, parentvar->data.aggregate.scalar));
8720 
8721  parentnewright = parentvar->data.aggregate.scalar * left + parentvar->data.aggregate.constant;
8722  parentnewleft = parentvar->data.aggregate.scalar * right + parentvar->data.aggregate.constant;
8723  }
8724  break;
8725 
8726  case SCIP_VARSTATUS_NEGATED: /* x = offset - x' -> x' = offset - x */
8727  assert(parentvar->negatedvar != NULL);
8728  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
8729  assert(parentvar->negatedvar->negatedvar == parentvar);
8730 
8731  parentnewright = -left + parentvar->data.negate.constant;
8732  parentnewleft = -right + parentvar->data.negate.constant;
8733  break;
8734 
8735  default:
8736  SCIPerrorMessage("unknown variable status\n");
8737  return SCIP_INVALIDDATA;
8738  }
8739 
8740  SCIPsetDebugMsg(set, "add local hole (%g,%g) to parent variable <%s>\n", parentnewleft, parentnewright, SCIPvarGetName(parentvar));
8741 
8742  /* perform hole added for parent variable */
8743  assert(blkmem != NULL);
8744  assert(SCIPsetIsLT(set, parentnewleft, parentnewright));
8745  SCIP_CALL( varProcessAddHoleLocal(parentvar, blkmem, set, stat, eventqueue,
8746  parentnewleft, parentnewright, &localadded) );
8747  assert(localadded);
8748  }
8749 
8750  return SCIP_OKAY;
8751 }
8752 
8753 /** adds a hole to the variable's current local domain */
8755  SCIP_VAR* var, /**< problem variable */
8756  BMS_BLKMEM* blkmem, /**< block memory */
8757  SCIP_SET* set, /**< global SCIP settings */
8758  SCIP_STAT* stat, /**< problem statistics */
8759  SCIP_EVENTQUEUE* eventqueue, /**< event queue, may be NULL for original variables */
8760  SCIP_Real left, /**< left bound of open interval in new hole */
8761  SCIP_Real right, /**< right bound of open interval in new hole */
8762  SCIP_Bool* added /**< pointer to store whether the hole was added */
8763  )
8764 {
8765  SCIP_Real childnewleft;
8766  SCIP_Real childnewright;
8767 
8768  assert(var != NULL);
8769 
8770  SCIPsetDebugMsg(set, "adding local hole (%g,%g) to <%s>\n", left, right, var->name);
8771 
8772  assert(set != NULL);
8773  assert(var->scip == set->scip);
8774  assert(SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
8775  assert(blkmem != NULL);
8776  assert(added != NULL);
8777 
8778  /* the interval should not be empty */
8779  assert(SCIPsetIsLT(set, left, right));
8780 
8781  /* the the interval bound should already be adjusted */
8782  assert(SCIPsetIsEQ(set, left, adjustedUb(set, SCIPvarGetType(var), left)));
8783  assert(SCIPsetIsEQ(set, right, adjustedLb(set, SCIPvarGetType(var), right)));
8784 
8785  /* the the interval should lay between the lower and upper bound */
8786  assert(SCIPsetIsGE(set, left, SCIPvarGetLbLocal(var)));
8787  assert(SCIPsetIsLE(set, right, SCIPvarGetUbLocal(var)));
8788 
8789  /* change bounds of attached variables */
8790  switch( SCIPvarGetStatus(var) )
8791  {
8793  if( var->data.original.transvar != NULL )
8794  {
8795  SCIP_CALL( SCIPvarAddHoleLocal(var->data.original.transvar, blkmem, set, stat, eventqueue,
8796  left, right, added) );
8797  }
8798  else
8799  {
8800  assert(set->stage == SCIP_STAGE_PROBLEM);
8801  SCIPstatIncrement(stat, set, domchgcount);
8802  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8803  }
8804  break;
8805 
8806  case SCIP_VARSTATUS_COLUMN:
8807  case SCIP_VARSTATUS_LOOSE:
8808  SCIPstatIncrement(stat, set, domchgcount);
8809  SCIP_CALL( varProcessAddHoleLocal(var, blkmem, set, stat, eventqueue, left, right, added) );
8810  break;
8811 
8812  case SCIP_VARSTATUS_FIXED:
8813  SCIPerrorMessage("cannot add domain hole to a fixed variable\n");
8814  return SCIP_INVALIDDATA;
8815 
8816  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
8817  assert(var->data.aggregate.var != NULL);
8818 
8819  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
8820  {
8821  /* a > 0 -> change lower bound of y */
8822  childnewleft = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8823  childnewright = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8824  }
8825  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
8826  {
8827  childnewright = (left - var->data.aggregate.constant)/var->data.aggregate.scalar;
8828  childnewleft = (right - var->data.aggregate.constant)/var->data.aggregate.scalar;
8829  }
8830  else
8831  {
8832  SCIPerrorMessage("scalar is zero in aggregation\n");
8833  return SCIP_INVALIDDATA;
8834  }
8835  SCIP_CALL( SCIPvarAddHoleLocal(var->data.aggregate.var, blkmem, set, stat, eventqueue,
8836  childnewleft, childnewright, added) );
8837  break;
8838 
8840  SCIPerrorMessage("cannot add domain hole to a multi-aggregated variable.\n");
8841  return SCIP_INVALIDDATA;
8842 
8843  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
8844  assert(var->negatedvar != NULL);
8846  assert(var->negatedvar->negatedvar == var);
8847 
8848  childnewright = -left + var->data.negate.constant;
8849  childnewleft = -right + var->data.negate.constant;
8850 
8851  SCIP_CALL( SCIPvarAddHoleLocal(var->negatedvar, blkmem, set, stat, eventqueue, childnewleft, childnewright, added) );
8852  break;
8853 
8854  default:
8855  SCIPerrorMessage("unknown variable status\n");
8856  return SCIP_INVALIDDATA;
8857  }
8858 
8859  return SCIP_OKAY;
8860 }
8861 
8862 /** resets the global and local bounds of original variable to their original values */
8864  SCIP_VAR* var, /**< problem variable */
8865  BMS_BLKMEM* blkmem, /**< block memory */
8866  SCIP_SET* set, /**< global SCIP settings */
8867  SCIP_STAT* stat /**< problem statistics */
8868  )
8869 {
8870  assert(var != NULL);
8871  assert(set != NULL);
8872  assert(var->scip == set->scip);
8873  assert(SCIPvarIsOriginal(var));
8874  /* resetting of bounds on original variables which have a transformed counterpart easily fails if, e.g.,
8875  * the transformed variable has been fixed */
8876  assert(SCIPvarGetTransVar(var) == NULL);
8877 
8878  /* copy the original bounds back to the global and local bounds */
8879  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.lb) );
8880  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, NULL, NULL, NULL, NULL, var->data.original.origdom.ub) );
8881  SCIP_CALL( SCIPvarChgLbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.lb) );
8882  SCIP_CALL( SCIPvarChgUbLocal(var, blkmem, set, stat, NULL, NULL, NULL, var->data.original.origdom.ub) );
8883 
8884  /* free the global and local holelists and duplicate the original ones */
8885  /**@todo this has also to be called recursively with methods similar to SCIPvarChgLbGlobal() */
8886  holelistFree(&var->glbdom.holelist, blkmem);
8887  holelistFree(&var->locdom.holelist, blkmem);
8888  SCIP_CALL( holelistDuplicate(&var->glbdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8889  SCIP_CALL( holelistDuplicate(&var->locdom.holelist, blkmem, set, var->data.original.origdom.holelist) );
8890 
8891  return SCIP_OKAY;
8892 }
8893 
8894 /** issues a IMPLADDED event on the given variable */
8895 static
8897  SCIP_VAR* var, /**< problem variable to change */
8898  BMS_BLKMEM* blkmem, /**< block memory */
8899  SCIP_SET* set, /**< global SCIP settings */
8900  SCIP_EVENTQUEUE* eventqueue /**< event queue */
8901  )
8902 {
8903  SCIP_EVENT* event;
8904 
8905  assert(var != NULL);
8906 
8907  /* issue IMPLADDED event on variable */
8908  SCIP_CALL( SCIPeventCreateImplAdded(&event, blkmem, var) );
8909  SCIP_CALL( SCIPeventqueueAdd(eventqueue, blkmem, set, NULL, NULL, NULL, NULL, &event) );
8910 
8911  return SCIP_OKAY;
8912 }
8913 
8914 /** actually performs the addition of a variable bound to the variable's vbound arrays */
8915 static
8917  SCIP_VAR* var, /**< problem variable x in x <= b*z + d or x >= b*z + d */
8918  BMS_BLKMEM* blkmem, /**< block memory */
8919  SCIP_SET* set, /**< global SCIP settings */
8920  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
8921  SCIP_BOUNDTYPE vbtype, /**< type of variable bound (LOWER or UPPER) */
8922  SCIP_VAR* vbvar, /**< variable z in x <= b*z + d or x >= b*z + d */
8923  SCIP_Real vbcoef, /**< coefficient b in x <= b*z + d or x >= b*z + d */
8924  SCIP_Real vbconstant /**< constant d in x <= b*z + d or x >= b*z + d */
8925  )
8926 {
8927  SCIP_Bool added;
8928 
8929  /* It can happen that the variable "var" and the variable "vbvar" are the same variable. For example if a variable
8930  * gets aggregated, the variable bounds (vbound) of that variable are copied to the other variable. A variable bound
8931  * variable of the aggregated variable might be the same as the one its gets aggregated too.
8932  *
8933  * If the variable "var" and the variable "vbvar" are the same, the variable bound which should be added here has to
8934  * be redundant. This is the case since an infeasibility should have be detected in the previous methods. As well as
8935  * the bounds of the variable which should be also already be tightened in the previous methods. Therefore, the
8936  * variable bound can be ignored.
8937  *
8938  * From the way the the variable bound system is implemented (detecting infeasibility, tighten bounds), the
8939  * equivalence of the variables should be checked here.
8940  */
8941  if( var == vbvar )
8942  {
8943  /* in this case the variable bound has to be redundant, this means for possible assignments to this variable; this
8944  * can be checked via the global bounds of the variable */
8945 #ifndef NDEBUG
8946  SCIP_Real lb;
8947  SCIP_Real ub;
8948 
8949  lb = SCIPvarGetLbGlobal(var);
8950  ub = SCIPvarGetUbGlobal(var);
8951 
8952  if(vbtype == SCIP_BOUNDTYPE_LOWER)
8953  {
8954  if( vbcoef > 0.0 )
8955  {
8956  assert(SCIPsetIsGE(set, lb, lb * vbcoef + vbconstant) );
8957  assert(SCIPsetIsGE(set, ub, ub * vbcoef + vbconstant) );
8958  }
8959  else
8960  {
8961  assert(SCIPsetIsGE(set, lb, ub * vbcoef + vbconstant) );
8962  assert(SCIPsetIsGE(set, ub, lb * vbcoef + vbconstant) );
8963  }
8964  }
8965  else
8966  {
8967  assert(vbtype == SCIP_BOUNDTYPE_UPPER);
8968  if( vbcoef > 0.0 )
8969  {
8970  assert(SCIPsetIsLE(set, lb, lb * vbcoef + vbconstant) );
8971  assert(SCIPsetIsLE(set, ub, ub * vbcoef + vbconstant) );
8972  }
8973  else
8974  {
8975  assert(SCIPsetIsLE(set, lb, ub * vbcoef + vbconstant) );
8976  assert(SCIPsetIsLE(set, ub, lb * vbcoef + vbconstant) );
8977  }
8978  }
8979 #endif
8980  SCIPsetDebugMsg(set, "redundant variable bound: <%s> %s %g<%s> %+g\n",
8981  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8982 
8983  return SCIP_OKAY;
8984  }
8985 
8986  SCIPsetDebugMsg(set, "adding variable bound: <%s> %s %g<%s> %+g\n",
8987  SCIPvarGetName(var), vbtype == SCIP_BOUNDTYPE_LOWER ? ">=" : "<=", vbcoef, SCIPvarGetName(vbvar), vbconstant);
8988 
8989  /* check variable bound on debugging solution */
8990  SCIP_CALL( SCIPdebugCheckVbound(set, var, vbtype, vbvar, vbcoef, vbconstant) ); /*lint !e506 !e774*/
8991 
8992  /* perform the addition */
8993  if( vbtype == SCIP_BOUNDTYPE_LOWER )
8994  {
8995  SCIP_CALL( SCIPvboundsAdd(&var->vlbs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
8996  }
8997  else
8998  {
8999  SCIP_CALL( SCIPvboundsAdd(&var->vubs, blkmem, set, vbtype, vbvar, vbcoef, vbconstant, &added) );
9000  }
9001  var->closestvblpcount = -1;
9002 
9003  if( added )
9004  {
9005  /* issue IMPLADDED event */
9006  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9007  }
9008 
9009  return SCIP_OKAY;
9010 }
9011 
9012 /** checks whether the given implication is redundant or infeasible w.r.t. the implied variables global bounds */
9013 static
9014 void checkImplic(
9015  SCIP_SET* set, /**< global SCIP settings */
9016  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9017  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9018  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9019  SCIP_Bool* redundant, /**< pointer to store whether the implication is redundant */
9020  SCIP_Bool* infeasible /**< pointer to store whether the implication is infeasible */
9021  )
9022 {
9023  SCIP_Real impllb;
9024  SCIP_Real implub;
9025 
9026  assert(redundant != NULL);
9027  assert(infeasible != NULL);
9028 
9029  impllb = SCIPvarGetLbGlobal(implvar);
9030  implub = SCIPvarGetUbGlobal(implvar);
9031  if( impltype == SCIP_BOUNDTYPE_LOWER )
9032  {
9033  *infeasible = SCIPsetIsFeasGT(set, implbound, implub);
9034  *redundant = SCIPsetIsFeasLE(set, implbound, impllb);
9035  }
9036  else
9037  {
9038  *infeasible = SCIPsetIsFeasLT(set, implbound, impllb);
9039  *redundant = SCIPsetIsFeasGE(set, implbound, implub);
9040  }
9041 }
9042 
9043 /** applies the given implication, if it is not redundant */
9044 static
9046  BMS_BLKMEM* blkmem, /**< block memory */
9047  SCIP_SET* set, /**< global SCIP settings */
9048  SCIP_STAT* stat, /**< problem statistics */
9049  SCIP_PROB* transprob, /**< transformed problem */
9050  SCIP_PROB* origprob, /**< original problem */
9051  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9052  SCIP_REOPT* reopt, /**< reoptimization data structure */
9053  SCIP_LP* lp, /**< current LP data */
9054  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9055  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9056  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9057  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9058  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9059  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9060  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9061  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9062  )
9063 {
9064  SCIP_Real implub;
9065  SCIP_Real impllb;
9066 
9067  assert(infeasible != NULL);
9068 
9069  *infeasible = FALSE;
9070 
9071  implub = SCIPvarGetUbGlobal(implvar);
9072  impllb = SCIPvarGetLbGlobal(implvar);
9073  if( impltype == SCIP_BOUNDTYPE_LOWER )
9074  {
9075  if( SCIPsetIsFeasGT(set, implbound, implub) )
9076  {
9077  /* the implication produces a conflict: the problem is infeasible */
9078  *infeasible = TRUE;
9079  }
9080  else if( SCIPsetIsFeasGT(set, implbound, impllb) )
9081  {
9082  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9083  * with the local bound, in this case we need to store the bound change as pending bound change
9084  */
9085  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9086  {
9087  assert(tree != NULL);
9088  assert(transprob != NULL);
9089  assert(SCIPprobIsTransformed(transprob));
9090 
9091  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9092  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_LOWER, FALSE) );
9093  }
9094  else
9095  {
9096  SCIP_CALL( SCIPvarChgLbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9097  }
9098 
9099  if( nbdchgs != NULL )
9100  (*nbdchgs)++;
9101  }
9102  }
9103  else
9104  {
9105  if( SCIPsetIsFeasLT(set, implbound, impllb) )
9106  {
9107  /* the implication produces a conflict: the problem is infeasible */
9108  *infeasible = TRUE;
9109  }
9110  else if( SCIPsetIsFeasLT(set, implbound, implub) )
9111  {
9112  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9113  * with the local bound, in this case we need to store the bound change as pending bound change
9114  */
9115  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9116  {
9117  assert(tree != NULL);
9118  assert(transprob != NULL);
9119  assert(SCIPprobIsTransformed(transprob));
9120 
9121  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9122  tree, reopt, lp, branchcand, eventqueue, cliquetable, implvar, implbound, SCIP_BOUNDTYPE_UPPER, FALSE) );
9123  }
9124  else
9125  {
9126  SCIP_CALL( SCIPvarChgUbGlobal(implvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, implbound) );
9127  }
9128 
9129  if( nbdchgs != NULL )
9130  (*nbdchgs)++;
9131  }
9132  }
9133 
9134  return SCIP_OKAY;
9135 }
9136 
9137 /** actually performs the addition of an implication to the variable's implication arrays,
9138  * and adds the corresponding implication or variable bound to the implied variable;
9139  * if the implication is conflicting, the variable is fixed to the opposite value;
9140  * if the variable is already fixed to the given value, the implication is performed immediately;
9141  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9142  */
9143 static
9145  SCIP_VAR* var, /**< problem variable */
9146  BMS_BLKMEM* blkmem, /**< block memory */
9147  SCIP_SET* set, /**< global SCIP settings */
9148  SCIP_STAT* stat, /**< problem statistics */
9149  SCIP_PROB* transprob, /**< transformed problem */
9150  SCIP_PROB* origprob, /**< original problem */
9151  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9152  SCIP_REOPT* reopt, /**< reoptimization data structure */
9153  SCIP_LP* lp, /**< current LP data */
9154  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9155  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9156  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9157  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9158  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9159  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9160  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9161  SCIP_Bool isshortcut, /**< is the implication a shortcut, i.e., added as part of the transitive closure of another implication? */
9162  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9163  int* nbdchgs, /**< pointer to count the number of performed bound changes, or NULL */
9164  SCIP_Bool* added /**< pointer to store whether an implication was added */
9165  )
9166 {
9167  SCIP_Bool redundant;
9168  SCIP_Bool conflict;
9169 
9170  assert(var != NULL);
9171  assert(SCIPvarIsActive(var));
9173  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9174  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9175  assert(infeasible != NULL);
9176  assert(added != NULL);
9177 
9178  /* check implication on debugging solution */
9179  SCIP_CALL( SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound) ); /*lint !e506 !e774*/
9180 
9181  *infeasible = FALSE;
9182  *added = FALSE;
9183 
9184  /* check, if the implication is redundant or infeasible */
9185  checkImplic(set, implvar, impltype, implbound, &redundant, &conflict);
9186  assert(!redundant || !conflict);
9187  if( redundant )
9188  return SCIP_OKAY;
9189 
9190  if( var == implvar )
9191  {
9192  /* special cases appear were a bound to a variable implies itself to be outside the bounds:
9193  * x == varfixing => x < 0 or x > 1
9194  */
9195  if( SCIPsetIsLT(set, implbound, 0.0) || SCIPsetIsGT(set, implbound, 1.0) )
9196  conflict = TRUE;
9197  else
9198  {
9199  /* variable implies itself: x == varfixing => x == (impltype == SCIP_BOUNDTYPE_LOWER) */
9200  assert(SCIPsetIsZero(set, implbound) || SCIPsetIsEQ(set, implbound, 1.0));
9201  assert(SCIPsetIsZero(set, implbound) == (impltype == SCIP_BOUNDTYPE_UPPER));
9202  assert(SCIPsetIsEQ(set, implbound, 1.0) == (impltype == SCIP_BOUNDTYPE_LOWER));
9203  conflict = conflict || ((varfixing == TRUE) == (impltype == SCIP_BOUNDTYPE_UPPER));
9204  if( !conflict )
9205  return SCIP_OKAY;
9206  }
9207  }
9208 
9209  /* check, if the variable is already fixed */
9210  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
9211  {
9212  /* if the variable is fixed to the given value, perform the implication; otherwise, ignore the implication */
9213  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
9214  {
9215  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
9216  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
9217  }
9218  return SCIP_OKAY;
9219  }
9220 
9221  assert((impltype == SCIP_BOUNDTYPE_LOWER && SCIPsetIsGT(set, implbound, SCIPvarGetLbGlobal(implvar)))
9222  || (impltype == SCIP_BOUNDTYPE_UPPER && SCIPsetIsLT(set, implbound, SCIPvarGetUbGlobal(implvar))));
9223 
9224  if( !conflict )
9225  {
9226  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9227 
9228  if( SCIPvarIsBinary(implvar) )
9229  {
9230  SCIP_VAR* vars[2];
9231  SCIP_Bool vals[2];
9232 
9233  assert(SCIPsetIsFeasEQ(set, implbound, 1.0) || SCIPsetIsFeasZero(set, implbound));
9234  assert((impltype == SCIP_BOUNDTYPE_UPPER) == SCIPsetIsFeasZero(set, implbound));
9235 
9236  vars[0] = var;
9237  vars[1] = implvar;
9238  vals[0] = varfixing;
9239  vals[1] = (impltype == SCIP_BOUNDTYPE_UPPER);
9240 
9241  /* add the clique to the clique table */
9242  SCIP_CALL( SCIPcliquetableAdd(cliquetable, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
9243  eventqueue, vars, vals, 2, FALSE, &conflict, nbdchgs) );
9244 
9245  if( !conflict )
9246  return SCIP_OKAY;
9247  }
9248  else
9249  {
9250  /* add implication x == 0/1 -> y <= b / y >= b to the implications list of x */
9251  SCIPsetDebugMsg(set, "adding implication: <%s> == %u ==> <%s> %s %g\n",
9252  SCIPvarGetName(var), varfixing,
9253  SCIPvarGetName(implvar), impltype == SCIP_BOUNDTYPE_UPPER ? "<=" : ">=", implbound);
9254  SCIP_CALL( SCIPimplicsAdd(&var->implics, blkmem, set, stat, varfixing, implvar, impltype, implbound,
9255  isshortcut, &conflict, added) );
9256  }
9257  }
9258  assert(!conflict || !(*added));
9259 
9260  /* on conflict, fix the variable to the opposite value */
9261  if( conflict )
9262  {
9263  SCIPsetDebugMsg(set, " -> implication yields a conflict: fix <%s> == %d\n", SCIPvarGetName(var), !varfixing);
9264 
9265  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9266  * with the local bound, in this case we need to store the bound change as pending bound change
9267  */
9268  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9269  {
9270  assert(tree != NULL);
9271  assert(transprob != NULL);
9272  assert(SCIPprobIsTransformed(transprob));
9273 
9274  if( varfixing )
9275  {
9276  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9277  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
9278  }
9279  else
9280  {
9281  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9282  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
9283  }
9284  }
9285  else
9286  {
9287  if( varfixing )
9288  {
9289  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
9290  }
9291  else
9292  {
9293  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
9294  }
9295  }
9296  if( nbdchgs != NULL )
9297  (*nbdchgs)++;
9298 
9299  return SCIP_OKAY;
9300  }
9301  else if( *added )
9302  {
9303  /* issue IMPLADDED event */
9304  SCIP_CALL( varEventImplAdded(var, blkmem, set, eventqueue) );
9305  }
9306  else
9307  {
9308  /* the implication was redundant: the inverse is also redundant */
9309  return SCIP_OKAY;
9310  }
9311 
9312  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9313 
9314  /* check, whether implied variable is binary */
9315  if( !SCIPvarIsBinary(implvar) )
9316  {
9317  SCIP_Real lb;
9318  SCIP_Real ub;
9319 
9320  /* add inverse variable bound to the variable bounds of y with global bounds y \in [lb,ub]:
9321  * x == 0 -> y <= b <-> y <= (ub - b)*x + b
9322  * x == 1 -> y <= b <-> y <= (b - ub)*x + ub
9323  * x == 0 -> y >= b <-> y >= (lb - b)*x + b
9324  * x == 1 -> y >= b <-> y >= (b - lb)*x + lb
9325  * for numerical reasons, ignore variable bounds with large absolute coefficient
9326  */
9327  lb = SCIPvarGetLbGlobal(implvar);
9328  ub = SCIPvarGetUbGlobal(implvar);
9329  if( impltype == SCIP_BOUNDTYPE_UPPER )
9330  {
9331  if( REALABS(implbound - ub) <= MAXABSVBCOEF )
9332  {
9333  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, var,
9334  varfixing ? implbound - ub : ub - implbound, varfixing ? ub : implbound) );
9335  }
9336  }
9337  else
9338  {
9339  if( REALABS(implbound - lb) <= MAXABSVBCOEF )
9340  {
9341  SCIP_CALL( varAddVbound(implvar, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, var,
9342  varfixing ? implbound - lb : lb - implbound, varfixing ? lb : implbound) );
9343  }
9344  }
9345  }
9346 
9347  return SCIP_OKAY;
9348 }
9349 
9350 /** adds transitive closure for binary implication x = a -> y = b */
9351 static
9353  SCIP_VAR* var, /**< problem variable */
9354  BMS_BLKMEM* blkmem, /**< block memory */
9355  SCIP_SET* set, /**< global SCIP settings */
9356  SCIP_STAT* stat, /**< problem statistics */
9357  SCIP_PROB* transprob, /**< transformed problem */
9358  SCIP_PROB* origprob, /**< original problem */
9359  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9360  SCIP_REOPT* reopt, /**< reoptimization data structure */
9361  SCIP_LP* lp, /**< current LP data */
9362  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9363  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9364  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9365  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9366  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9367  SCIP_Bool implvarfixing, /**< fixing b in implication */
9368  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9369  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9370  )
9371 {
9372  SCIP_VAR** implvars;
9373  SCIP_BOUNDTYPE* impltypes;
9374  SCIP_Real* implbounds;
9375  int nimpls;
9376  int i;
9377 
9378  *infeasible = FALSE;
9379 
9380  /* binary variable: implications of implvar */
9381  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9382  implvars = SCIPimplicsGetVars(implvar->implics, implvarfixing);
9383  impltypes = SCIPimplicsGetTypes(implvar->implics, implvarfixing);
9384  implbounds = SCIPimplicsGetBounds(implvar->implics, implvarfixing);
9385 
9386  /* if variable has too many implications, the implication graph may become too dense */
9387  i = MIN(nimpls, MAXIMPLSCLOSURE) - 1;
9388 
9389  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9390  * implvars[i] is fixed, s.t. the implication y == varfixing -> z <= b / z >= b is deleted; this affects the
9391  * array over which we currently iterate; the only thing that can happen, is that elements of the array are
9392  * deleted; in this case, the subsequent elements are moved to the front; if we iterate from back to front, the
9393  * only thing that can happen is that we add the same implication twice - this does no harm
9394  */
9395  while ( i >= 0 && !(*infeasible) )
9396  {
9397  SCIP_Bool added;
9398 
9399  assert(implvars[i] != implvar);
9400 
9401  /* we have x == varfixing -> y == implvarfixing -> z <= b / z >= b:
9402  * add implication x == varfixing -> z <= b / z >= b to the implications list of x
9403  */
9404  if( SCIPvarIsActive(implvars[i]) )
9405  {
9406  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9407  eventqueue, varfixing, implvars[i], impltypes[i], implbounds[i], TRUE, infeasible, nbdchgs, &added) );
9408  assert(SCIPimplicsGetNImpls(implvar->implics, implvarfixing) <= nimpls);
9409  nimpls = SCIPimplicsGetNImpls(implvar->implics, implvarfixing);
9410  i = MIN(i, nimpls); /* some elements from the array could have been removed */
9411  }
9412  --i;
9413  }
9414 
9415  return SCIP_OKAY;
9416 }
9417 
9418 /** adds given implication to the variable's implication list, and adds all implications directly implied by this
9419  * implication to the variable's implication list;
9420  * if the implication is conflicting, the variable is fixed to the opposite value;
9421  * if the variable is already fixed to the given value, the implication is performed immediately;
9422  * if the implication is redundant with respect to the variables' global bounds, it is ignored
9423  */
9424 static
9426  SCIP_VAR* var, /**< problem variable */
9427  BMS_BLKMEM* blkmem, /**< block memory */
9428  SCIP_SET* set, /**< global SCIP settings */
9429  SCIP_STAT* stat, /**< problem statistics */
9430  SCIP_PROB* transprob, /**< transformed problem */
9431  SCIP_PROB* origprob, /**< original problem */
9432  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9433  SCIP_REOPT* reopt, /**< reoptimization data structure */
9434  SCIP_LP* lp, /**< current LP data */
9435  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9436  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9437  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9438  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
9439  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
9440  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
9441  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
9442  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9443  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9444  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
9445  )
9446 {
9447  SCIP_Bool added;
9448 
9449  assert(var != NULL);
9450  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
9451  assert(SCIPvarIsActive(var));
9452  assert(implvar != NULL);
9453  assert(SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED);
9454  assert(infeasible != NULL);
9455 
9456  /* add implication x == varfixing -> y <= b / y >= b to the implications list of x */
9457  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable, branchcand,
9458  eventqueue, varfixing, implvar, impltype, implbound, FALSE, infeasible, nbdchgs, &added) );
9459 
9460  if( *infeasible || var == implvar || !transitive || !added )
9461  return SCIP_OKAY;
9462 
9463  assert(SCIPvarIsActive(implvar)); /* a fixed implvar would either cause a redundancy or infeasibility */
9464 
9465  /* add transitive closure */
9466  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
9467  {
9468  SCIP_Bool implvarfixing;
9469 
9470  implvarfixing = (impltype == SCIP_BOUNDTYPE_LOWER);
9471 
9472  /* binary variable: implications of implvar */
9473  SCIP_CALL( varAddTransitiveBinaryClosureImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9474  cliquetable, branchcand, eventqueue, varfixing, implvar, implvarfixing, infeasible, nbdchgs) );
9475 
9476  /* inverse implication */
9477  if( !(*infeasible) )
9478  {
9479  SCIP_CALL( varAddTransitiveBinaryClosureImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9480  cliquetable, branchcand, eventqueue, !implvarfixing, var, !varfixing, infeasible, nbdchgs) );
9481  }
9482  }
9483  else
9484  {
9485  /* non-binary variable: variable lower bounds of implvar */
9486  if( impltype == SCIP_BOUNDTYPE_UPPER && implvar->vlbs != NULL )
9487  {
9488  SCIP_VAR** vlbvars;
9489  SCIP_Real* vlbcoefs;
9490  SCIP_Real* vlbconstants;
9491  int nvlbvars;
9492  int i;
9493 
9494  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9495  vlbvars = SCIPvboundsGetVars(implvar->vlbs);
9496  vlbcoefs = SCIPvboundsGetCoefs(implvar->vlbs);
9497  vlbconstants = SCIPvboundsGetConstants(implvar->vlbs);
9498 
9499  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9500  * vlbvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9501  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9502  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9503  * is that we add the same implication twice - this does no harm
9504  */
9505  i = nvlbvars-1;
9506  while ( i >= 0 && !(*infeasible) )
9507  {
9508  assert(vlbvars[i] != implvar);
9509  assert(!SCIPsetIsZero(set, vlbcoefs[i]));
9510 
9511  /* we have x == varfixing -> y <= b and y >= c*z + d:
9512  * c > 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9513  * c < 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9514  *
9515  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9516  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9517  * aggregation variable (the one which will stay active);
9518  *
9519  * W.l.o.g. we consider the variable upper bounds for now. Let "vubvar" be a variable upper bound of
9520  * the aggregated variable "aggvar"; During that copying of that variable upper bound variable
9521  * "vubvar" the variable lower and upper bounds of this variable "vubvar" are also considered; note
9522  * that the "aggvar" can be a variable lower bound variable of the variable "vubvar"; Due to that
9523  * situation it can happen that we reach that code place where "vlbvars[i] == aggvar". In particular
9524  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9525  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9526  * have to explicitly check that the active variable has not a variable status
9527  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9528  */
9529  if( SCIPvarIsActive(vlbvars[i]) && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vlbvars[i]) != SCIP_VARSTATUS_NEGATED )
9530  {
9531  SCIP_Real vbimplbound;
9532 
9533  vbimplbound = (implbound - vlbconstants[i])/vlbcoefs[i];
9534  if( vlbcoefs[i] >= 0.0 )
9535  {
9536  vbimplbound = adjustedUb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9537  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9538  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9539  infeasible, nbdchgs, &added) );
9540  }
9541  else
9542  {
9543  vbimplbound = adjustedLb(set, SCIPvarGetType(vlbvars[i]), vbimplbound);
9544  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9545  branchcand, eventqueue, varfixing, vlbvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9546  infeasible, nbdchgs, &added) );
9547  }
9548  nvlbvars = SCIPvboundsGetNVbds(implvar->vlbs);
9549  i = MIN(i, nvlbvars); /* some elements from the array could have been removed */
9550  }
9551  --i;
9552  }
9553  }
9554 
9555  /* non-binary variable: variable upper bounds of implvar */
9556  if( impltype == SCIP_BOUNDTYPE_LOWER && implvar->vubs != NULL )
9557  {
9558  SCIP_VAR** vubvars;
9559  SCIP_Real* vubcoefs;
9560  SCIP_Real* vubconstants;
9561  int nvubvars;
9562  int i;
9563 
9564  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9565  vubvars = SCIPvboundsGetVars(implvar->vubs);
9566  vubcoefs = SCIPvboundsGetCoefs(implvar->vubs);
9567  vubconstants = SCIPvboundsGetConstants(implvar->vubs);
9568 
9569  /* we have to iterate from back to front, because in varAddImplic() it may happen that a conflict is detected and
9570  * vubvars[i] is fixed, s.t. the variable bound is deleted; this affects the array over which we currently
9571  * iterate; the only thing that can happen, is that elements of the array are deleted; in this case, the
9572  * subsequent elements are moved to the front; if we iterate from back to front, the only thing that can happen
9573  * is that we add the same implication twice - this does no harm
9574  */
9575  i = nvubvars-1;
9576  while ( i >= 0 && !(*infeasible) )
9577  {
9578  assert(vubvars[i] != implvar);
9579  assert(!SCIPsetIsZero(set, vubcoefs[i]));
9580 
9581  /* we have x == varfixing -> y >= b and y <= c*z + d:
9582  * c > 0: add implication x == varfixing -> z >= (b-d)/c to the implications list of x
9583  * c < 0: add implication x == varfixing -> z <= (b-d)/c to the implications list of x
9584  *
9585  * @note during an aggregation the aggregated variable "aggrvar" (the one which will have the status
9586  * SCIP_VARSTATUS_AGGREGATED afterwards) copies its variable lower and uppers bounds to the
9587  * aggregation variable (the one which will stay active);
9588  *
9589  * W.l.o.g. we consider the variable lower bounds for now. Let "vlbvar" be a variable lower bound of
9590  * the aggregated variable "aggvar"; During that copying of that variable lower bound variable
9591  * "vlbvar" the variable lower and upper bounds of this variable "vlbvar" are also considered; note
9592  * that the "aggvar" can be a variable upper bound variable of the variable "vlbvar"; Due to that
9593  * situation it can happen that we reach that code place where "vubvars[i] == aggvar". In particular
9594  * the "aggvar" has already the variable status SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED
9595  * but is still active since the aggregation is not finished yet (in SCIPvarAggregate()); therefore we
9596  * have to explicitly check that the active variable has not a variable status
9597  * SCIP_VARSTATUS_AGGREGATED or SCIP_VARSTATUS_NEGATED;
9598  */
9599  if( SCIPvarIsActive(vubvars[i]) && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_AGGREGATED && SCIPvarGetStatus(vubvars[i]) != SCIP_VARSTATUS_NEGATED )
9600  {
9601  SCIP_Real vbimplbound;
9602 
9603  vbimplbound = (implbound - vubconstants[i])/vubcoefs[i];
9604  if( vubcoefs[i] >= 0.0 )
9605  {
9606  vbimplbound = adjustedLb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9607  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9608  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_LOWER, vbimplbound, TRUE,
9609  infeasible, nbdchgs, &added) );
9610  }
9611  else
9612  {
9613  vbimplbound = adjustedUb(set, SCIPvarGetType(vubvars[i]), vbimplbound);
9614  SCIP_CALL( varAddImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9615  branchcand, eventqueue, varfixing, vubvars[i], SCIP_BOUNDTYPE_UPPER, vbimplbound, TRUE,
9616  infeasible, nbdchgs, &added) );
9617  }
9618  nvubvars = SCIPvboundsGetNVbds(implvar->vubs);
9619  i = MIN(i, nvubvars); /* some elements from the array could have been removed */
9620  }
9621  --i;
9622  }
9623  }
9624  }
9625 
9626  return SCIP_OKAY;
9627 }
9628 
9629 /** informs variable x about a globally valid variable lower bound x >= b*z + d with integer variable z;
9630  * if z is binary, the corresponding valid implication for z is also added;
9631  * improves the global bounds of the variable and the vlb variable if possible
9632  */
9634  SCIP_VAR* var, /**< problem variable */
9635  BMS_BLKMEM* blkmem, /**< block memory */
9636  SCIP_SET* set, /**< global SCIP settings */
9637  SCIP_STAT* stat, /**< problem statistics */
9638  SCIP_PROB* transprob, /**< transformed problem */
9639  SCIP_PROB* origprob, /**< original problem */
9640  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
9641  SCIP_REOPT* reopt, /**< reoptimization data structure */
9642  SCIP_LP* lp, /**< current LP data */
9643  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
9644  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
9645  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
9646  SCIP_VAR* vlbvar, /**< variable z in x >= b*z + d */
9647  SCIP_Real vlbcoef, /**< coefficient b in x >= b*z + d */
9648  SCIP_Real vlbconstant, /**< constant d in x >= b*z + d */
9649  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
9650  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
9651  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
9652  )
9653 {
9654  assert(var != NULL);
9655  assert(set != NULL);
9656  assert(var->scip == set->scip);
9657  assert(SCIPvarGetType(vlbvar) != SCIP_VARTYPE_CONTINUOUS);
9658  assert(infeasible != NULL);
9659 
9660  SCIPsetDebugMsg(set, "adding variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9661 
9662  *infeasible = FALSE;
9663  if( nbdchgs != NULL )
9664  *nbdchgs = 0;
9665 
9666  switch( SCIPvarGetStatus(var) )
9667  {
9669  assert(var->data.original.transvar != NULL);
9670  SCIP_CALL( SCIPvarAddVlb(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9671  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef, vlbconstant, transitive, infeasible, nbdchgs) );
9672  break;
9673 
9674  case SCIP_VARSTATUS_COLUMN:
9675  case SCIP_VARSTATUS_LOOSE:
9676  case SCIP_VARSTATUS_FIXED:
9677  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
9678  SCIP_CALL( SCIPvarGetProbvarSum(&vlbvar, set, &vlbcoef, &vlbconstant) );
9679  SCIPsetDebugMsg(set, " -> transformed to variable lower bound <%s> >= %g<%s> + %g\n", SCIPvarGetName(var), vlbcoef, SCIPvarGetName(vlbvar), vlbconstant);
9680 
9681  /* if the vlb coefficient is zero, just update the lower bound of the variable */
9682  if( SCIPsetIsZero(set, vlbcoef) )
9683  {
9684  if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetUbGlobal(var)) )
9685  *infeasible = TRUE;
9686  else if( SCIPsetIsFeasGT(set, vlbconstant, SCIPvarGetLbGlobal(var)) )
9687  {
9688  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9689  * with the local bound, in this case we need to store the bound change as pending bound change
9690  */
9691  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9692  {
9693  assert(tree != NULL);
9694  assert(transprob != NULL);
9695  assert(SCIPprobIsTransformed(transprob));
9696 
9697  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9698  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vlbconstant, SCIP_BOUNDTYPE_LOWER, FALSE) );
9699  }
9700  else
9701  {
9702  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vlbconstant) );
9703  }
9704 
9705  if( nbdchgs != NULL )
9706  (*nbdchgs)++;
9707  }
9708  }
9709  else if( SCIPvarIsActive(vlbvar) )
9710  {
9711  SCIP_Real xlb;
9712  SCIP_Real xub;
9713  SCIP_Real zlb;
9714  SCIP_Real zub;
9715  SCIP_Real minvlb;
9716  SCIP_Real maxvlb;
9717 
9719  assert(vlbcoef != 0.0);
9720 
9721  minvlb = -SCIPsetInfinity(set);
9722  maxvlb = SCIPsetInfinity(set);
9723 
9724  xlb = SCIPvarGetLbGlobal(var);
9725  xub = SCIPvarGetUbGlobal(var);
9726  zlb = SCIPvarGetLbGlobal(vlbvar);
9727  zub = SCIPvarGetUbGlobal(vlbvar);
9728 
9729  /* improve global bounds of vlb variable, and calculate minimal and maximal value of variable bound */
9730  if( vlbcoef >= 0.0 )
9731  {
9732  SCIP_Real newzub;
9733 
9734  if( !SCIPsetIsInfinity(set, xub) )
9735  {
9736  /* x >= b*z + d -> z <= (x-d)/b */
9737  newzub = (xub - vlbconstant)/vlbcoef;
9738 
9739  /* return if the new bound is less than -infinity */
9740  if( SCIPsetIsInfinity(set, REALABS(newzub)) )
9741  return SCIP_OKAY;
9742 
9743  if( SCIPsetIsFeasLT(set, newzub, zlb) )
9744  {
9745  *infeasible = TRUE;
9746  return SCIP_OKAY;
9747  }
9748  if( SCIPsetIsFeasLT(set, newzub, zub) )
9749  {
9750  /* bound might be adjusted due to integrality condition */
9751  newzub = adjustedUb(set, SCIPvarGetType(vlbvar), newzub);
9752 
9753  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9754  * with the local bound, in this case we need to store the bound change as pending bound change
9755  */
9756  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9757  {
9758  assert(tree != NULL);
9759  assert(transprob != NULL);
9760  assert(SCIPprobIsTransformed(transprob));
9761 
9762  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9763  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
9764  }
9765  else
9766  {
9767  SCIP_CALL( SCIPvarChgUbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
9768  }
9769  zub = newzub;
9770 
9771  if( nbdchgs != NULL )
9772  (*nbdchgs)++;
9773  }
9774  maxvlb = vlbcoef * zub + vlbconstant;
9775  if( !SCIPsetIsInfinity(set, -zlb) )
9776  minvlb = vlbcoef * zlb + vlbconstant;
9777  }
9778  else
9779  {
9780  if( !SCIPsetIsInfinity(set, zub) )
9781  maxvlb = vlbcoef * zub + vlbconstant;
9782  if( !SCIPsetIsInfinity(set, -zlb) )
9783  minvlb = vlbcoef * zlb + vlbconstant;
9784  }
9785  }
9786  else
9787  {
9788  SCIP_Real newzlb;
9789 
9790  if( !SCIPsetIsInfinity(set, xub) )
9791  {
9792  /* x >= b*z + d -> z >= (x-d)/b */
9793  newzlb = (xub - vlbconstant)/vlbcoef;
9794 
9795  /* return if the new bound is larger than infinity */
9796  if( SCIPsetIsInfinity(set, REALABS(newzlb)) )
9797  return SCIP_OKAY;
9798 
9799  if( SCIPsetIsFeasGT(set, newzlb, zub) )
9800  {
9801  *infeasible = TRUE;
9802  return SCIP_OKAY;
9803  }
9804  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
9805  {
9806  /* bound might be adjusted due to integrality condition */
9807  newzlb = adjustedLb(set, SCIPvarGetType(vlbvar), newzlb);
9808 
9809  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9810  * with the local bound, in this case we need to store the bound change as pending bound change
9811  */
9812  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9813  {
9814  assert(tree != NULL);
9815  assert(transprob != NULL);
9816  assert(SCIPprobIsTransformed(transprob));
9817 
9818  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9819  tree, reopt, lp, branchcand, eventqueue, cliquetable, vlbvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9820  }
9821  else
9822  {
9823  SCIP_CALL( SCIPvarChgLbGlobal(vlbvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
9824  }
9825  zlb = newzlb;
9826 
9827  if( nbdchgs != NULL )
9828  (*nbdchgs)++;
9829  }
9830  maxvlb = vlbcoef * zlb + vlbconstant;
9831  if( !SCIPsetIsInfinity(set, zub) )
9832  minvlb = vlbcoef * zub + vlbconstant;
9833  }
9834  else
9835  {
9836  if( !SCIPsetIsInfinity(set, -zlb) )
9837  maxvlb = vlbcoef * zlb + vlbconstant;
9838  if( !SCIPsetIsInfinity(set, zub) )
9839  minvlb = vlbcoef * zub + vlbconstant;
9840  }
9841  }
9842  if( maxvlb < minvlb )
9843  maxvlb = minvlb;
9844 
9845  /* adjust bounds due to integrality of variable */
9846  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9847  maxvlb = adjustedLb(set, SCIPvarGetType(var), maxvlb);
9848 
9849  /* check bounds for feasibility */
9850  if( SCIPsetIsFeasGT(set, minvlb, xub) || (var == vlbvar && SCIPsetIsEQ(set, vlbcoef, 1.0) && SCIPsetIsFeasPositive(set, vlbconstant)) )
9851  {
9852  *infeasible = TRUE;
9853  return SCIP_OKAY;
9854  }
9855  /* improve global lower bound of variable */
9856  if( SCIPsetIsFeasGT(set, minvlb, xlb) )
9857  {
9858  /* bound might be adjusted due to integrality condition */
9859  minvlb = adjustedLb(set, SCIPvarGetType(var), minvlb);
9860 
9861  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
9862  * with the local bound, in this case we need to store the bound change as pending bound change
9863  */
9864  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
9865  {
9866  assert(tree != NULL);
9867  assert(transprob != NULL);
9868  assert(SCIPprobIsTransformed(transprob));
9869 
9870  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
9871  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, minvlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
9872  }
9873  else
9874  {
9875  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, minvlb) );
9876  }
9877  xlb = minvlb;
9878 
9879  if( nbdchgs != NULL )
9880  (*nbdchgs)++;
9881  }
9882  minvlb = xlb;
9883 
9884  /* improve variable bound for binary z by moving the variable's global bound to the vlb constant */
9885  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9886  {
9887  /* b > 0: x >= (maxvlb - minvlb) * z + minvlb
9888  * b < 0: x >= (minvlb - maxvlb) * z + maxvlb
9889  */
9890 
9891  assert(!SCIPsetIsInfinity(set, maxvlb) && !SCIPsetIsInfinity(set, -minvlb));
9892 
9893  if( vlbcoef >= 0.0 )
9894  {
9895  vlbcoef = maxvlb - minvlb;
9896  vlbconstant = minvlb;
9897  }
9898  else
9899  {
9900  vlbcoef = minvlb - maxvlb;
9901  vlbconstant = maxvlb;
9902  }
9903  }
9904 
9905  /* add variable bound to the variable bounds list */
9906  if( SCIPsetIsFeasGT(set, maxvlb, xlb) )
9907  {
9908  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
9909  assert(!SCIPsetIsZero(set, vlbcoef));
9910 
9911  /* if one of the variables is binary, add the corresponding implication to the variable's implication
9912  * list, thereby also adding the variable bound (or implication) to the other variable
9913  */
9914  if( SCIPvarGetType(vlbvar) == SCIP_VARTYPE_BINARY )
9915  {
9916  /* add corresponding implication:
9917  * b > 0, x >= b*z + d <-> z == 1 -> x >= b+d
9918  * b < 0, x >= b*z + d <-> z == 0 -> x >= d
9919  */
9920  SCIP_CALL( varAddTransitiveImplic(vlbvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9921  cliquetable, branchcand, eventqueue, (vlbcoef >= 0.0), var, SCIP_BOUNDTYPE_LOWER, maxvlb, transitive,
9922  infeasible, nbdchgs) );
9923  }
9924  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
9925  {
9926  /* add corresponding implication:
9927  * b > 0, x >= b*z + d <-> x == 0 -> z <= -d/b
9928  * b < 0, x >= b*z + d <-> x == 0 -> z >= -d/b
9929  */
9930  SCIP_Real implbound;
9931  implbound = -vlbconstant/vlbcoef;
9932 
9933  /* tighten the implication bound if the variable is integer */
9934  if( SCIPvarIsIntegral(vlbvar) )
9935  {
9936  if( vlbcoef >= 0 )
9937  implbound = SCIPsetFloor(set, implbound);
9938  else
9939  implbound = SCIPsetCeil(set, implbound);
9940  }
9941  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9942  cliquetable, branchcand, eventqueue, FALSE, vlbvar, (vlbcoef >= 0.0 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER),
9943  implbound, transitive, infeasible, nbdchgs) );
9944  }
9945  else
9946  {
9947  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_LOWER, vlbvar, vlbcoef, vlbconstant) );
9948  }
9949  }
9950  }
9951  break;
9952 
9954  /* x = a*y + c: x >= b*z + d <=> a*y + c >= b*z + d <=> y >= b/a * z + (d-c)/a, if a > 0
9955  * y <= b/a * z + (d-c)/a, if a < 0
9956  */
9957  assert(var->data.aggregate.var != NULL);
9958  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
9959  {
9960  /* a > 0 -> add variable lower bound */
9961  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9962  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9963  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9964  }
9965  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
9966  {
9967  /* a < 0 -> add variable upper bound */
9968  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
9969  cliquetable, branchcand, eventqueue, vlbvar, vlbcoef/var->data.aggregate.scalar,
9970  (vlbconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
9971  }
9972  else
9973  {
9974  SCIPerrorMessage("scalar is zero in aggregation\n");
9975  return SCIP_INVALIDDATA;
9976  }
9977  break;
9978 
9980  /* nothing to do here */
9981  break;
9982 
9984  /* x = offset - x': x >= b*z + d <=> offset - x' >= b*z + d <=> x' <= -b*z + (offset-d) */
9985  assert(var->negatedvar != NULL);
9987  assert(var->negatedvar->negatedvar == var);
9988  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
9989  branchcand, eventqueue, vlbvar, -vlbcoef, var->data.negate.constant - vlbconstant, transitive, infeasible,
9990  nbdchgs) );
9991  break;
9992 
9993  default:
9994  SCIPerrorMessage("unknown variable status\n");
9995  return SCIP_INVALIDDATA;
9996  }
9997 
9998  return SCIP_OKAY;
9999 }
10000 
10001 /** informs variable x about a globally valid variable upper bound x <= b*z + d with integer variable z;
10002  * if z is binary, the corresponding valid implication for z is also added;
10003  * updates the global bounds of the variable and the vub variable correspondingly
10004  */
10006  SCIP_VAR* var, /**< problem variable */
10007  BMS_BLKMEM* blkmem, /**< block memory */
10008  SCIP_SET* set, /**< global SCIP settings */
10009  SCIP_STAT* stat, /**< problem statistics */
10010  SCIP_PROB* transprob, /**< transformed problem */
10011  SCIP_PROB* origprob, /**< original problem */
10012  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10013  SCIP_REOPT* reopt, /**< reoptimization data structure */
10014  SCIP_LP* lp, /**< current LP data */
10015  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10016  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10017  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10018  SCIP_VAR* vubvar, /**< variable z in x <= b*z + d */
10019  SCIP_Real vubcoef, /**< coefficient b in x <= b*z + d */
10020  SCIP_Real vubconstant, /**< constant d in x <= b*z + d */
10021  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10022  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10023  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10024  )
10025 {
10026  assert(var != NULL);
10027  assert(set != NULL);
10028  assert(var->scip == set->scip);
10029  assert(SCIPvarGetType(vubvar) != SCIP_VARTYPE_CONTINUOUS);
10030  assert(infeasible != NULL);
10031 
10032  SCIPsetDebugMsg(set, "adding variable upper bound <%s> <= %g<%s> + %g\n", SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10033 
10034  *infeasible = FALSE;
10035  if( nbdchgs != NULL )
10036  *nbdchgs = 0;
10037 
10038  switch( SCIPvarGetStatus(var) )
10039  {
10041  assert(var->data.original.transvar != NULL);
10042  SCIP_CALL( SCIPvarAddVub(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10043  cliquetable, branchcand, eventqueue, vubvar, vubcoef, vubconstant, transitive, infeasible, nbdchgs) );
10044  break;
10045 
10046  case SCIP_VARSTATUS_COLUMN:
10047  case SCIP_VARSTATUS_LOOSE:
10048  case SCIP_VARSTATUS_FIXED:
10049  /* transform b*z + d into the corresponding sum after transforming z to an active problem variable */
10050  SCIP_CALL( SCIPvarGetProbvarSum(&vubvar, set, &vubcoef, &vubconstant) );
10051  SCIPsetDebugMsg(set, " -> transformed to variable upper bound <%s> <= %g<%s> + %g\n",
10052  SCIPvarGetName(var), vubcoef, SCIPvarGetName(vubvar), vubconstant);
10053 
10054  /* if the vub coefficient is zero, just update the upper bound of the variable */
10055  if( SCIPsetIsZero(set, vubcoef) )
10056  {
10057  if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetLbGlobal(var)) )
10058  *infeasible = TRUE;
10059  else if( SCIPsetIsFeasLT(set, vubconstant, SCIPvarGetUbGlobal(var)) )
10060  {
10061  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10062  * with the local bound, in this case we need to store the bound change as pending bound change
10063  */
10064  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10065  {
10066  assert(tree != NULL);
10067  assert(transprob != NULL);
10068  assert(SCIPprobIsTransformed(transprob));
10069 
10070  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10071  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, vubconstant, SCIP_BOUNDTYPE_UPPER, FALSE) );
10072  }
10073  else
10074  {
10075  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, vubconstant) );
10076  }
10077 
10078  if( nbdchgs != NULL )
10079  (*nbdchgs)++;
10080  }
10081  }
10082  else if( SCIPvarIsActive(vubvar) )
10083  {
10084  SCIP_Real xlb;
10085  SCIP_Real xub;
10086  SCIP_Real zlb;
10087  SCIP_Real zub;
10088  SCIP_Real minvub;
10089  SCIP_Real maxvub;
10090 
10092  assert(vubcoef != 0.0);
10093 
10094  minvub = -SCIPsetInfinity(set);
10095  maxvub = SCIPsetInfinity(set);
10096 
10097  xlb = SCIPvarGetLbGlobal(var);
10098  xub = SCIPvarGetUbGlobal(var);
10099  zlb = SCIPvarGetLbGlobal(vubvar);
10100  zub = SCIPvarGetUbGlobal(vubvar);
10101 
10102  /* improve global bounds of vub variable, and calculate minimal and maximal value of variable bound */
10103  if( vubcoef >= 0.0 )
10104  {
10105  SCIP_Real newzlb;
10106 
10107  if( !SCIPsetIsInfinity(set, -xlb) )
10108  {
10109  /* x <= b*z + d -> z >= (x-d)/b */
10110  newzlb = (xlb - vubconstant)/vubcoef;
10111  if( SCIPsetIsFeasGT(set, newzlb, zub) )
10112  {
10113  *infeasible = TRUE;
10114  return SCIP_OKAY;
10115  }
10116  if( SCIPsetIsFeasGT(set, newzlb, zlb) )
10117  {
10118  /* bound might be adjusted due to integrality condition */
10119  newzlb = adjustedLb(set, SCIPvarGetType(vubvar), newzlb);
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, vubvar, newzlb, SCIP_BOUNDTYPE_LOWER, FALSE) );
10132  }
10133  else
10134  {
10135  SCIP_CALL( SCIPvarChgLbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzlb) );
10136  }
10137  zlb = newzlb;
10138 
10139  if( nbdchgs != NULL )
10140  (*nbdchgs)++;
10141  }
10142  minvub = vubcoef * zlb + vubconstant;
10143  if( !SCIPsetIsInfinity(set, zub) )
10144  maxvub = vubcoef * zub + vubconstant;
10145  }
10146  else
10147  {
10148  if( !SCIPsetIsInfinity(set, zub) )
10149  maxvub = vubcoef * zub + vubconstant;
10150  if( !SCIPsetIsInfinity(set, -zlb) )
10151  minvub = vubcoef * zlb + vubconstant;
10152  }
10153  }
10154  else
10155  {
10156  SCIP_Real newzub;
10157 
10158  if( !SCIPsetIsInfinity(set, -xlb) )
10159  {
10160  /* x <= b*z + d -> z <= (x-d)/b */
10161  newzub = (xlb - vubconstant)/vubcoef;
10162  if( SCIPsetIsFeasLT(set, newzub, zlb) )
10163  {
10164  *infeasible = TRUE;
10165  return SCIP_OKAY;
10166  }
10167  if( SCIPsetIsFeasLT(set, newzub, zub) )
10168  {
10169  /* bound might be adjusted due to integrality condition */
10170  newzub = adjustedUb(set, SCIPvarGetType(vubvar), newzub);
10171 
10172  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10173  * with the local bound, in this case we need to store the bound change as pending bound change
10174  */
10175  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10176  {
10177  assert(tree != NULL);
10178  assert(transprob != NULL);
10179  assert(SCIPprobIsTransformed(transprob));
10180 
10181  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10182  tree, reopt, lp, branchcand, eventqueue, cliquetable, vubvar, newzub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10183  }
10184  else
10185  {
10186  SCIP_CALL( SCIPvarChgUbGlobal(vubvar, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, newzub) );
10187  }
10188  zub = newzub;
10189 
10190  if( nbdchgs != NULL )
10191  (*nbdchgs)++;
10192  }
10193  minvub = vubcoef * zub + vubconstant;
10194  if( !SCIPsetIsInfinity(set, -zlb) )
10195  maxvub = vubcoef * zlb + vubconstant;
10196  }
10197  else
10198  {
10199  if( !SCIPsetIsInfinity(set, zub) )
10200  minvub = vubcoef * zub + vubconstant;
10201  if( !SCIPsetIsInfinity(set, -zlb) )
10202  maxvub = vubcoef * zlb + vubconstant;
10203  }
10204 
10205  }
10206  if( minvub > maxvub )
10207  minvub = maxvub;
10208 
10209  /* adjust bounds due to integrality of vub variable */
10210  minvub = adjustedUb(set, SCIPvarGetType(var), minvub);
10211  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10212 
10213  /* check bounds for feasibility */
10214  if( SCIPsetIsFeasLT(set, maxvub, xlb) || (var == vubvar && SCIPsetIsEQ(set, vubcoef, 1.0) && SCIPsetIsFeasNegative(set, vubconstant)) )
10215  {
10216  *infeasible = TRUE;
10217  return SCIP_OKAY;
10218  }
10219  /* improve global upper bound of variable */
10220  if( SCIPsetIsFeasLT(set, maxvub, xub) )
10221  {
10222  /* bound might be adjusted due to integrality condition */
10223  maxvub = adjustedUb(set, SCIPvarGetType(var), maxvub);
10224 
10225  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10226  * with the local bound, in this case we need to store the bound change as pending bound change
10227  */
10228  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10229  {
10230  assert(tree != NULL);
10231  assert(transprob != NULL);
10232  assert(SCIPprobIsTransformed(transprob));
10233 
10234  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10235  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, maxvub, SCIP_BOUNDTYPE_UPPER, FALSE) );
10236  }
10237  else
10238  {
10239  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, maxvub) );
10240  }
10241  xub = maxvub;
10242 
10243  if( nbdchgs != NULL )
10244  (*nbdchgs)++;
10245  }
10246  maxvub = xub;
10247 
10248  /* improve variable bound for binary z by moving the variable's global bound to the vub constant */
10249  if( SCIPvarIsBinary(vubvar) )
10250  {
10251  /* b > 0: x <= (maxvub - minvub) * z + minvub
10252  * b < 0: x <= (minvub - maxvub) * z + maxvub
10253  */
10254 
10255  assert(!SCIPsetIsInfinity(set, maxvub) && !SCIPsetIsInfinity(set, -minvub));
10256 
10257  if( vubcoef >= 0.0 )
10258  {
10259  vubcoef = maxvub - minvub;
10260  vubconstant = minvub;
10261  }
10262  else
10263  {
10264  vubcoef = minvub - maxvub;
10265  vubconstant = maxvub;
10266  }
10267  }
10268 
10269  /* add variable bound to the variable bounds list */
10270  if( SCIPsetIsFeasLT(set, minvub, xub) )
10271  {
10272  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_FIXED);
10273  assert(!SCIPsetIsZero(set, vubcoef));
10274 
10275  /* if one of the variables is binary, add the corresponding implication to the variable's implication
10276  * list, thereby also adding the variable bound (or implication) to the other variable
10277  */
10278  if( SCIPvarGetType(vubvar) == SCIP_VARTYPE_BINARY )
10279  {
10280  /* add corresponding implication:
10281  * b > 0, x <= b*z + d <-> z == 0 -> x <= d
10282  * b < 0, x <= b*z + d <-> z == 1 -> x <= b+d
10283  */
10284  SCIP_CALL( varAddTransitiveImplic(vubvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10285  cliquetable, branchcand, eventqueue, (vubcoef < 0.0), var, SCIP_BOUNDTYPE_UPPER, minvub, transitive,
10286  infeasible, nbdchgs) );
10287  }
10288  else if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
10289  {
10290  /* add corresponding implication:
10291  * b > 0, x <= b*z + d <-> x == 1 -> z >= (1-d)/b
10292  * b < 0, x <= b*z + d <-> x == 1 -> z <= (1-d)/b
10293  */
10294  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10295  cliquetable, branchcand, eventqueue, TRUE, vubvar, (vubcoef >= 0.0 ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER),
10296  (1.0-vubconstant)/vubcoef, transitive, infeasible, nbdchgs) );
10297  }
10298  else
10299  {
10300  SCIP_CALL( varAddVbound(var, blkmem, set, eventqueue, SCIP_BOUNDTYPE_UPPER, vubvar, vubcoef, vubconstant) );
10301  }
10302  }
10303  }
10304  break;
10305 
10307  /* x = a*y + c: x <= b*z + d <=> a*y + c <= b*z + d <=> y <= b/a * z + (d-c)/a, if a > 0
10308  * y >= b/a * z + (d-c)/a, if a < 0
10309  */
10310  assert(var->data.aggregate.var != NULL);
10311  if( SCIPsetIsPositive(set, var->data.aggregate.scalar) )
10312  {
10313  /* a > 0 -> add variable upper bound */
10314  SCIP_CALL( SCIPvarAddVub(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10315  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10316  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10317  }
10318  else if( SCIPsetIsNegative(set, var->data.aggregate.scalar) )
10319  {
10320  /* a < 0 -> add variable lower bound */
10321  SCIP_CALL( SCIPvarAddVlb(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10322  cliquetable, branchcand, eventqueue, vubvar, vubcoef/var->data.aggregate.scalar,
10323  (vubconstant - var->data.aggregate.constant)/var->data.aggregate.scalar, transitive, infeasible, nbdchgs) );
10324  }
10325  else
10326  {
10327  SCIPerrorMessage("scalar is zero in aggregation\n");
10328  return SCIP_INVALIDDATA;
10329  }
10330  break;
10331 
10333  /* nothing to do here */
10334  break;
10335 
10337  /* x = offset - x': x <= b*z + d <=> offset - x' <= b*z + d <=> x' >= -b*z + (offset-d) */
10338  assert(var->negatedvar != NULL);
10340  assert(var->negatedvar->negatedvar == var);
10341  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10342  branchcand, eventqueue, vubvar, -vubcoef, var->data.negate.constant - vubconstant, transitive, infeasible,
10343  nbdchgs) );
10344  break;
10345 
10346  default:
10347  SCIPerrorMessage("unknown variable status\n");
10348  return SCIP_INVALIDDATA;
10349  }
10350 
10351  return SCIP_OKAY;
10352 }
10353 
10354 /** informs binary variable x about a globally valid implication: x == 0 or x == 1 ==> y <= b or y >= b;
10355  * also adds the corresponding implication or variable bound to the implied variable;
10356  * if the implication is conflicting, the variable is fixed to the opposite value;
10357  * if the variable is already fixed to the given value, the implication is performed immediately;
10358  * if the implication is redundant with respect to the variables' global bounds, it is ignored
10359  */
10361  SCIP_VAR* var, /**< problem variable */
10362  BMS_BLKMEM* blkmem, /**< block memory */
10363  SCIP_SET* set, /**< global SCIP settings */
10364  SCIP_STAT* stat, /**< problem statistics */
10365  SCIP_PROB* transprob, /**< transformed problem */
10366  SCIP_PROB* origprob, /**< original problem */
10367  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10368  SCIP_REOPT* reopt, /**< reoptimization data structure */
10369  SCIP_LP* lp, /**< current LP data */
10370  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10371  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10372  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10373  SCIP_Bool varfixing, /**< FALSE if y should be added in implications for x == 0, TRUE for x == 1 */
10374  SCIP_VAR* implvar, /**< variable y in implication y <= b or y >= b */
10375  SCIP_BOUNDTYPE impltype, /**< type of implication y <= b (SCIP_BOUNDTYPE_UPPER) or y >= b (SCIP_BOUNDTYPE_LOWER) */
10376  SCIP_Real implbound, /**< bound b in implication y <= b or y >= b */
10377  SCIP_Bool transitive, /**< should transitive closure of implication also be added? */
10378  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10379  int* nbdchgs /**< pointer to store the number of performed bound changes, or NULL */
10380  )
10381 {
10382  assert(var != NULL);
10383  assert(set != NULL);
10384  assert(var->scip == set->scip);
10385  assert(SCIPvarGetType(var) == SCIP_VARTYPE_BINARY);
10386  assert(infeasible != NULL);
10387 
10388  *infeasible = FALSE;
10389  if( nbdchgs != NULL )
10390  *nbdchgs = 0;
10391 
10392  switch( SCIPvarGetStatus(var) )
10393  {
10395  assert(var->data.original.transvar != NULL);
10396  SCIP_CALL( SCIPvarAddImplic(var->data.original.transvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10397  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10398  nbdchgs) );
10399  break;
10400 
10401  case SCIP_VARSTATUS_COLUMN:
10402  case SCIP_VARSTATUS_LOOSE:
10403  /* if the variable is fixed (although it has no FIXED status), and varfixing corresponds to the fixed value of
10404  * the variable, the implication can be applied directly;
10405  * otherwise, add implication to the implications list (and add inverse of implication to the implied variable)
10406  */
10407  if( SCIPvarGetLbGlobal(var) > 0.5 || SCIPvarGetUbGlobal(var) < 0.5 )
10408  {
10409  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10410  {
10411  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10412  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10413  }
10414  }
10415  else
10416  {
10417  SCIP_CALL( SCIPvarGetProbvarBound(&implvar, &implbound, &impltype) );
10418  SCIPvarAdjustBd(implvar, set, impltype, &implbound);
10419  if( SCIPvarIsActive(implvar) || SCIPvarGetStatus(implvar) == SCIP_VARSTATUS_FIXED )
10420  {
10421  SCIP_CALL( varAddTransitiveImplic(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10422  branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10423  }
10424  }
10425  break;
10426 
10427  case SCIP_VARSTATUS_FIXED:
10428  /* if varfixing corresponds to the fixed value of the variable, the implication can be applied directly */
10429  if( varfixing == (SCIPvarGetLbGlobal(var) > 0.5) )
10430  {
10431  SCIP_CALL( applyImplic(blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand, eventqueue,
10432  cliquetable, implvar, impltype, implbound, infeasible, nbdchgs) );
10433  }
10434  break;
10435 
10437  /* implication added for x == 1:
10438  * x == 1 && x = 1*z + 0 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10439  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10440  * implication added for x == 0:
10441  * x == 0 && x = 1*z + 0 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10442  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10443  *
10444  * use only binary variables z
10445  */
10446  assert(var->data.aggregate.var != NULL);
10447  if( SCIPvarIsBinary(var->data.aggregate.var) )
10448  {
10449  assert( (SCIPsetIsEQ(set, var->data.aggregate.scalar, 1.0) && SCIPsetIsZero(set, var->data.aggregate.constant))
10450  || (SCIPsetIsEQ(set, var->data.aggregate.scalar, -1.0) && SCIPsetIsEQ(set, var->data.aggregate.constant, 1.0)) );
10451 
10452  if( var->data.aggregate.scalar > 0 )
10453  {
10454  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10455  cliquetable, branchcand, eventqueue, varfixing, implvar, impltype, implbound, transitive, infeasible,
10456  nbdchgs) );
10457  }
10458  else
10459  {
10460  SCIP_CALL( SCIPvarAddImplic(var->data.aggregate.var, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10461  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible,
10462  nbdchgs) );
10463  }
10464  }
10465  break;
10466 
10468  /* nothing to do here */
10469  break;
10470 
10472  /* implication added for x == 1:
10473  * x == 1 && x = -1*z + 1 ==> y <= b or y >= b <==> z <= 0 ==> y <= b or y >= b
10474  * implication added for x == 0:
10475  * x == 0 && x = -1*z + 1 ==> y <= b or y >= b <==> z >= 1 ==> y <= b or y >= b
10476  */
10477  assert(var->negatedvar != NULL);
10479  assert(var->negatedvar->negatedvar == var);
10480  assert(SCIPvarIsBinary(var->negatedvar));
10481 
10483  {
10484  SCIP_CALL( SCIPvarAddImplic(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10485  cliquetable, branchcand, eventqueue, !varfixing, implvar, impltype, implbound, transitive, infeasible, nbdchgs) );
10486  }
10487  /* in case one both variables are not of binary type we have to add the implication as variable bounds */
10488  else
10489  {
10490  /* if the implied variable is of binary type exchange the variables */
10491  if( SCIPvarGetType(implvar) == SCIP_VARTYPE_BINARY )
10492  {
10493  SCIP_CALL( SCIPvarAddImplic(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10494  branchcand, eventqueue, (impltype == SCIP_BOUNDTYPE_UPPER) ? TRUE : FALSE, var->negatedvar,
10495  varfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER, varfixing ? 1.0 : 0.0, transitive,
10496  infeasible, nbdchgs) );
10497  }
10498  else
10499  {
10500  /* both variables are not of binary type but are implicit binary; in that case we can only add this
10501  * implication as variable bounds
10502  */
10503 
10504  /* add variable lower bound on the negation of var */
10505  if( varfixing )
10506  {
10507  /* (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
10508  * as variable lower bound
10509  */
10510  SCIP_CALL( SCIPvarAddVlb(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10511  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : -1.0,
10512  (impltype == SCIP_BOUNDTYPE_UPPER) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10513  }
10514  else
10515  {
10516  /* (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
10517  * as variable upper bound
10518  */
10519  SCIP_CALL( SCIPvarAddVub(var->negatedvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp,
10520  cliquetable, branchcand, eventqueue, implvar, (impltype == SCIP_BOUNDTYPE_UPPER) ? -1.0 : 1.0,
10521  (impltype == SCIP_BOUNDTYPE_UPPER) ? 1.0 : 0.0, transitive, infeasible, nbdchgs) );
10522  }
10523 
10524  /* add variable bound on implvar */
10525  if( impltype == SCIP_BOUNDTYPE_UPPER )
10526  {
10527  /* (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
10528  * as variable upper bound
10529  */
10530  SCIP_CALL( SCIPvarAddVub(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10531  branchcand, eventqueue, var->negatedvar, (varfixing) ? 1.0 : -1.0,
10532  (varfixing) ? 0.0 : 1.0, transitive, infeasible, nbdchgs) );
10533  }
10534  else
10535  {
10536  /* (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
10537  * as variable upper bound
10538  */
10539  SCIP_CALL( SCIPvarAddVlb(implvar, blkmem, set, stat, transprob, origprob, tree, reopt, lp, cliquetable,
10540  branchcand, eventqueue, var->negatedvar, (varfixing) ? -1.0 : 1.0, (varfixing) ? 1.0 : 0.0,
10541  transitive, infeasible, nbdchgs) );
10542  }
10543  }
10544  }
10545  break;
10546 
10547  default:
10548  SCIPerrorMessage("unknown variable status\n");
10549  return SCIP_INVALIDDATA;
10550  }
10551 
10552  return SCIP_OKAY;
10553 }
10554 
10555 /** returns whether there is an implication x == varfixing -> y <= b or y >= b in the implication graph;
10556  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10557  * both variables must be active, variable x must be binary
10558  */
10560  SCIP_VAR* var, /**< problem variable x */
10561  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10562  SCIP_VAR* implvar, /**< variable y to search for */
10563  SCIP_BOUNDTYPE impltype /**< type of implication y <=/>= b to search for */
10564  )
10565 {
10566  assert(var != NULL);
10567  assert(implvar != NULL);
10568  assert(SCIPvarIsActive(var));
10569  assert(SCIPvarIsActive(implvar));
10570  assert(SCIPvarIsBinary(var));
10571 
10572  return var->implics != NULL && SCIPimplicsContainsImpl(var->implics, varfixing, implvar, impltype);
10573 }
10574 
10575 /** returns whether there is an implication x == varfixing -> y == implvarfixing in the implication graph;
10576  * implications that are represented as cliques in the clique table are not regarded (use SCIPvarsHaveCommonClique());
10577  * both variables must be active binary variables
10578  */
10580  SCIP_VAR* var, /**< problem variable x */
10581  SCIP_Bool varfixing, /**< FALSE if y should be searched in implications for x == 0, TRUE for x == 1 */
10582  SCIP_VAR* implvar, /**< variable y to search for */
10583  SCIP_Bool implvarfixing /**< value of the implied variable to search for */
10584  )
10585 {
10586  assert(SCIPvarIsBinary(implvar));
10587 
10588  return SCIPvarHasImplic(var, varfixing, implvar, implvarfixing ? SCIP_BOUNDTYPE_LOWER : SCIP_BOUNDTYPE_UPPER);
10589 }
10590 
10591 /** fixes the bounds of a binary variable to the given value, counting bound changes and detecting infeasibility */
10593  SCIP_VAR* var, /**< problem variable */
10594  BMS_BLKMEM* blkmem, /**< block memory */
10595  SCIP_SET* set, /**< global SCIP settings */
10596  SCIP_STAT* stat, /**< problem statistics */
10597  SCIP_PROB* transprob, /**< transformed problem */
10598  SCIP_PROB* origprob, /**< original problem */
10599  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10600  SCIP_REOPT* reopt, /**< reoptimization data structure */
10601  SCIP_LP* lp, /**< current LP data */
10602  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10603  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10604  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10605  SCIP_Bool value, /**< value to fix variable to */
10606  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10607  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10608  )
10609 {
10610  assert(var != NULL);
10611  assert(set != NULL);
10612  assert(var->scip == set->scip);
10613  assert(infeasible != NULL);
10614 
10615  *infeasible = FALSE;
10616 
10617  if( value == FALSE )
10618  {
10619  if( var->glbdom.lb > 0.5 )
10620  *infeasible = TRUE;
10621  else if( var->glbdom.ub > 0.5 )
10622  {
10623  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10624  * with the local bound, in this case we need to store the bound change as pending bound change
10625  */
10626  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10627  {
10628  assert(tree != NULL);
10629  assert(transprob != NULL);
10630  assert(SCIPprobIsTransformed(transprob));
10631 
10632  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10633  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 0.0, SCIP_BOUNDTYPE_UPPER, FALSE) );
10634  }
10635  else
10636  {
10637  SCIP_CALL( SCIPvarChgUbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 0.0) );
10638  }
10639 
10640  if( nbdchgs != NULL )
10641  (*nbdchgs)++;
10642  }
10643  }
10644  else
10645  {
10646  if( var->glbdom.ub < 0.5 )
10647  *infeasible = TRUE;
10648  else if( var->glbdom.lb < 0.5 )
10649  {
10650  /* during solving stage it can happen that the global bound change cannot be applied directly because it conflicts
10651  * with the local bound, in this case we need to store the bound change as pending bound change
10652  */
10653  if( SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING )
10654  {
10655  assert(tree != NULL);
10656  assert(transprob != NULL);
10657  assert(SCIPprobIsTransformed(transprob));
10658 
10659  SCIP_CALL( SCIPnodeAddBoundchg(SCIPtreeGetRootNode(tree), blkmem, set, stat, transprob, origprob,
10660  tree, reopt, lp, branchcand, eventqueue, cliquetable, var, 1.0, SCIP_BOUNDTYPE_LOWER, FALSE) );
10661  }
10662  else
10663  {
10664  SCIP_CALL( SCIPvarChgLbGlobal(var, blkmem, set, stat, lp, branchcand, eventqueue, cliquetable, 1.0) );
10665  }
10666 
10667  if( nbdchgs != NULL )
10668  (*nbdchgs)++;
10669  }
10670  }
10671 
10672  /* during presolving, the variable should have been removed immediately from all its cliques */
10673  assert(SCIPsetGetStage(set) >= SCIP_STAGE_SOLVING || var->cliquelist == NULL);
10674 
10675  return SCIP_OKAY;
10676 }
10677 
10678 /** adds the variable to the given clique and updates the list of cliques the binary variable is member of;
10679  * if the variable now appears twice in the clique with the same value, it is fixed to the opposite value;
10680  * if the variable now appears twice in the clique with opposite values, all other variables are fixed to
10681  * the opposite of the value they take in the clique
10682  */
10684  SCIP_VAR* var, /**< problem variable */
10685  BMS_BLKMEM* blkmem, /**< block memory */
10686  SCIP_SET* set, /**< global SCIP settings */
10687  SCIP_STAT* stat, /**< problem statistics */
10688  SCIP_PROB* transprob, /**< transformed problem */
10689  SCIP_PROB* origprob, /**< original problem */
10690  SCIP_TREE* tree, /**< branch and bound tree if in solving stage */
10691  SCIP_REOPT* reopt, /**< reoptimization data structure */
10692  SCIP_LP* lp, /**< current LP data */
10693  SCIP_BRANCHCAND* branchcand, /**< branching candidate storage */
10694  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
10695  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10696  SCIP_Bool value, /**< value of the variable in the clique */
10697  SCIP_CLIQUE* clique, /**< clique the variable should be added to */
10698  SCIP_Bool* infeasible, /**< pointer to store whether an infeasibility was detected */
10699  int* nbdchgs /**< pointer to count the number of performed bound changes, or NULL */
10700  )
10701 {
10702  assert(var != NULL);
10703  assert(set != NULL);
10704  assert(var->scip == set->scip);
10705  assert(SCIPvarIsBinary(var));
10706  assert(infeasible != NULL);
10707 
10708  *infeasible = FALSE;
10709 
10710  /* get corresponding active problem variable */
10711  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10716  assert(SCIPvarIsBinary(var));
10717 
10718  /* only column and loose variables may be member of a clique */
10720  {
10721  SCIP_Bool doubleentry;
10722  SCIP_Bool oppositeentry;
10723 
10724  /* add variable to clique */
10725  SCIP_CALL( SCIPcliqueAddVar(clique, blkmem, set, var, value, &doubleentry, &oppositeentry) );
10726 
10727  /* add clique to variable's clique list */
10728  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10729 
10730  /* check consistency of cliquelist */
10731  SCIPcliquelistCheck(var->cliquelist, var);
10732 
10733  /* if the variable now appears twice with the same value in the clique, it can be fixed to the opposite value */
10734  if( doubleentry )
10735  {
10736  SCIP_CALL( SCIPvarFixBinary(var, blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10737  eventqueue, cliquetable, !value, infeasible, nbdchgs) );
10738  }
10739 
10740  /* if the variable appears with both values in the clique, all other variables of the clique can be fixed
10741  * to the opposite of the value they take in the clique
10742  */
10743  if( oppositeentry )
10744  {
10745  SCIP_VAR** vars;
10746  SCIP_Bool* values;
10747  int nvars;
10748  int i;
10749 
10750  nvars = SCIPcliqueGetNVars(clique);
10751  vars = SCIPcliqueGetVars(clique);
10752  values = SCIPcliqueGetValues(clique);
10753  for( i = 0; i < nvars && !(*infeasible); ++i )
10754  {
10755  if( vars[i] == var )
10756  continue;
10757 
10758  SCIP_CALL( SCIPvarFixBinary(vars[i], blkmem, set, stat, transprob, origprob, tree, reopt, lp, branchcand,
10759  eventqueue, cliquetable, !values[i], infeasible, nbdchgs) );
10760  }
10761  }
10762  }
10763 
10764  return SCIP_OKAY;
10765 }
10766 
10767 /** adds a filled clique to the cliquelists of all corresponding variables */
10769  SCIP_VAR** vars, /**< problem variables */
10770  SCIP_Bool* values, /**< values of the variables in the clique */
10771  int nvars, /**< number of problem variables */
10772  BMS_BLKMEM* blkmem, /**< block memory */
10773  SCIP_SET* set, /**< global SCIP settings */
10774  SCIP_CLIQUE* clique /**< clique that contains all given variables and values */
10775  )
10776 {
10777  SCIP_VAR* var;
10778  int v;
10779 
10780  assert(vars != NULL);
10781  assert(values != NULL);
10782  assert(nvars > 0);
10783  assert(set != NULL);
10784  assert(blkmem != NULL);
10785  assert(clique != NULL);
10786 
10787  for( v = nvars - 1; v >= 0; --v )
10788  {
10789  var = vars[v];
10790  assert(SCIPvarIsBinary(var));
10792 
10793  /* add clique to variable's clique list */
10794  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, values[v], clique) );
10795 
10796  /* check consistency of cliquelist */
10797  SCIPcliquelistCheck(var->cliquelist, var);
10798  }
10799 
10800  return SCIP_OKAY;
10801 }
10802 
10803 /** adds a clique to the list of cliques of the given binary variable, but does not change the clique
10804  * itself
10805  */
10807  SCIP_VAR* var, /**< problem variable */
10808  BMS_BLKMEM* blkmem, /**< block memory */
10809  SCIP_SET* set, /**< global SCIP settings */
10810  SCIP_Bool value, /**< value of the variable in the clique */
10811  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10812  )
10813 {
10814  assert(var != NULL);
10815  assert(SCIPvarIsBinary(var));
10817 
10818  /* add clique to variable's clique list */
10819  SCIP_CALL( SCIPcliquelistAdd(&var->cliquelist, blkmem, set, value, clique) );
10820 
10821  return SCIP_OKAY;
10822 }
10823 
10824 
10825 /** deletes a clique from the list of cliques the binary variable is member of, but does not change the clique
10826  * itself
10827  */
10829  SCIP_VAR* var, /**< problem variable */
10830  BMS_BLKMEM* blkmem, /**< block memory */
10831  SCIP_Bool value, /**< value of the variable in the clique */
10832  SCIP_CLIQUE* clique /**< clique that should be removed from the variable's clique list */
10833  )
10834 {
10835  assert(var != NULL);
10836  assert(SCIPvarIsBinary(var));
10837 
10838  /* delete clique from variable's clique list */
10839  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10840 
10841  return SCIP_OKAY;
10842 }
10843 
10844 /** deletes the variable from the given clique and updates the list of cliques the binary variable is member of */
10846  SCIP_VAR* var, /**< problem variable */
10847  BMS_BLKMEM* blkmem, /**< block memory */
10848  SCIP_CLIQUETABLE* cliquetable, /**< clique table data structure */
10849  SCIP_Bool value, /**< value of the variable in the clique */
10850  SCIP_CLIQUE* clique /**< clique the variable should be removed from */
10851  )
10852 {
10853  assert(var != NULL);
10854  assert(SCIPvarIsBinary(var));
10855 
10856  /* get corresponding active problem variable */
10857  SCIP_CALL( SCIPvarGetProbvarBinary(&var, &value) );
10862  assert(SCIPvarIsBinary(var));
10863 
10864  /* only column and loose variables may be member of a clique */
10866  {
10867  /* delete clique from variable's clique list */
10868  SCIP_CALL( SCIPcliquelistDel(&var->cliquelist, blkmem, value, clique) );
10869 
10870  /* delete variable from clique */
10871  SCIPcliqueDelVar(clique, cliquetable, var, value);
10872 
10873  /* check consistency of cliquelist */
10874  SCIPcliquelistCheck(var->cliquelist, var);
10875  }
10876 
10877  return SCIP_OKAY;
10878 }
10879 
10880 /** returns whether there is a clique that contains both given variable/value pairs;
10881  * the variables must be active binary variables;
10882  * if regardimplics is FALSE, only the cliques in the clique table are looked at;
10883  * if regardimplics is TRUE, both the cliques and the implications of the implication graph are regarded
10884  *
10885  * @note a variable with it's negated variable are NOT! in a clique
10886  * @note a variable with itself are in a clique
10887  */
10889  SCIP_VAR* var1, /**< first variable */
10890  SCIP_Bool value1, /**< value of first variable */
10891  SCIP_VAR* var2, /**< second variable */
10892  SCIP_Bool value2, /**< value of second variable */
10893  SCIP_Bool regardimplics /**< should the implication graph also be searched for a clique? */
10894  )
10895 {
10896  assert(var1 != NULL);
10897  assert(var2 != NULL);
10898  assert(SCIPvarIsActive(var1));
10899  assert(SCIPvarIsActive(var2));
10900  assert(SCIPvarIsBinary(var1));
10901  assert(SCIPvarIsBinary(var2));
10902 
10903  return (SCIPcliquelistsHaveCommonClique(var1->cliquelist, value1, var2->cliquelist, value2)
10904  || (regardimplics && SCIPvarHasImplic(var1, value1, var2, value2 ? SCIP_BOUNDTYPE_UPPER : SCIP_BOUNDTYPE_LOWER)));
10905 }
10906 
10907 /** actually changes the branch factor of the variable and of all parent variables */
10908 static
10910  SCIP_VAR* var, /**< problem variable */
10911  SCIP_SET* set, /**< global SCIP settings */
10912  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10913  )
10914 {
10915  SCIP_VAR* parentvar;
10916  SCIP_Real eps;
10917  int i;
10918 
10919  assert(var != NULL);
10920  assert(set != NULL);
10921  assert(var->scip == set->scip);
10922 
10923  /* only use positive values */
10924  eps = SCIPsetEpsilon(set);
10925  branchfactor = MAX(branchfactor, eps);
10926 
10927  SCIPsetDebugMsg(set, "process changing branch factor of <%s> from %f to %f\n", var->name, var->branchfactor, branchfactor);
10928 
10929  if( SCIPsetIsEQ(set, branchfactor, var->branchfactor) )
10930  return SCIP_OKAY;
10931 
10932  /* change the branch factor */
10933  var->branchfactor = branchfactor;
10934 
10935  /* process parent variables */
10936  for( i = 0; i < var->nparentvars; ++i )
10937  {
10938  parentvar = var->parentvars[i];
10939  assert(parentvar != NULL);
10940 
10941  switch( SCIPvarGetStatus(parentvar) )
10942  {
10944  /* do not change priorities across the border between transformed and original problem */
10945  break;
10946 
10947  case SCIP_VARSTATUS_COLUMN:
10948  case SCIP_VARSTATUS_LOOSE:
10949  case SCIP_VARSTATUS_FIXED:
10951  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
10952  SCIPABORT();
10953  return SCIP_INVALIDDATA; /*lint !e527*/
10954 
10957  SCIP_CALL( varProcessChgBranchFactor(parentvar, set, branchfactor) );
10958  break;
10959 
10960  default:
10961  SCIPerrorMessage("unknown variable status\n");
10962  SCIPABORT();
10963  return SCIP_ERROR; /*lint !e527*/
10964  }
10965  }
10966 
10967  return SCIP_OKAY;
10968 }
10969 
10970 /** sets the branch factor of the variable; this value can be used in the branching methods to scale the score
10971  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
10972  */
10974  SCIP_VAR* var, /**< problem variable */
10975  SCIP_SET* set, /**< global SCIP settings */
10976  SCIP_Real branchfactor /**< factor to weigh variable's branching score with */
10977  )
10978 {
10979  int v;
10980 
10981  assert(var != NULL);
10982  assert(set != NULL);
10983  assert(var->scip == set->scip);
10984  assert(branchfactor >= 0.0);
10985 
10986  SCIPdebugMessage("changing branch factor of <%s> from %g to %g\n", var->name, var->branchfactor, branchfactor);
10987 
10988  if( SCIPsetIsEQ(set, var->branchfactor, branchfactor) )
10989  return SCIP_OKAY;
10990 
10991  /* change priorities of attached variables */
10992  switch( SCIPvarGetStatus(var) )
10993  {
10995  if( var->data.original.transvar != NULL )
10996  {
10997  SCIP_CALL( SCIPvarChgBranchFactor(var->data.original.transvar, set, branchfactor) );
10998  }
10999  else
11000  {
11001  assert(set->stage == SCIP_STAGE_PROBLEM);
11002  var->branchfactor = branchfactor;
11003  }
11004  break;
11005 
11006  case SCIP_VARSTATUS_COLUMN:
11007  case SCIP_VARSTATUS_LOOSE:
11008  case SCIP_VARSTATUS_FIXED:
11009  SCIP_CALL( varProcessChgBranchFactor(var, set, branchfactor) );
11010  break;
11011 
11013  assert(var->data.aggregate.var != NULL);
11014  SCIP_CALL( SCIPvarChgBranchFactor(var->data.aggregate.var, set, branchfactor) );
11015  break;
11016 
11018  assert(!var->donotmultaggr);
11019  for( v = 0; v < var->data.multaggr.nvars; ++v )
11020  {
11021  SCIP_CALL( SCIPvarChgBranchFactor(var->data.multaggr.vars[v], set, branchfactor) );
11022  }
11023  break;
11024 
11026  assert(var->negatedvar != NULL);
11028  assert(var->negatedvar->negatedvar == var);
11029  SCIP_CALL( SCIPvarChgBranchFactor(var->negatedvar, set, branchfactor) );
11030  break;
11031 
11032  default:
11033  SCIPerrorMessage("unknown variable status\n");
11034  SCIPABORT();
11035  return SCIP_ERROR; /*lint !e527*/
11036  }
11037 
11038  return SCIP_OKAY;
11039 }
11040 
11041 /** actually changes the branch priority of the variable and of all parent variables */
11042 static
11044  SCIP_VAR* var, /**< problem variable */
11045  int branchpriority /**< branching priority of the variable */
11046  )
11047 {
11048  SCIP_VAR* parentvar;
11049  int i;
11050 
11051  assert(var != NULL);
11052 
11053  SCIPdebugMessage("process changing branch priority of <%s> from %d to %d\n",
11054  var->name, var->branchpriority, branchpriority);
11055 
11056  if( branchpriority == var->branchpriority )
11057  return SCIP_OKAY;
11058 
11059  /* change the branch priority */
11060  var->branchpriority = branchpriority;
11061 
11062  /* process parent variables */
11063  for( i = 0; i < var->nparentvars; ++i )
11064  {
11065  parentvar = var->parentvars[i];
11066  assert(parentvar != NULL);
11067 
11068  switch( SCIPvarGetStatus(parentvar) )
11069  {
11071  /* do not change priorities across the border between transformed and original problem */
11072  break;
11073 
11074  case SCIP_VARSTATUS_COLUMN:
11075  case SCIP_VARSTATUS_LOOSE:
11076  case SCIP_VARSTATUS_FIXED:
11078  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11079  SCIPABORT();
11080  return SCIP_INVALIDDATA; /*lint !e527*/
11081 
11084  SCIP_CALL( varProcessChgBranchPriority(parentvar, branchpriority) );
11085  break;
11086 
11087  default:
11088  SCIPerrorMessage("unknown variable status\n");
11089  return SCIP_ERROR;
11090  }
11091  }
11092 
11093  return SCIP_OKAY;
11094 }
11095 
11096 /** sets the branch priority of the variable; variables with higher branch priority are always preferred to variables
11097  * with lower priority in selection of branching variable
11098  */
11100  SCIP_VAR* var, /**< problem variable */
11101  int branchpriority /**< branching priority of the variable */
11102  )
11103 {
11104  int v;
11105 
11106  assert(var != NULL);
11107 
11108  SCIPdebugMessage("changing branch priority of <%s> from %d to %d\n", var->name, var->branchpriority, branchpriority);
11109 
11110  if( var->branchpriority == branchpriority )
11111  return SCIP_OKAY;
11112 
11113  /* change priorities of attached variables */
11114  switch( SCIPvarGetStatus(var) )
11115  {
11117  if( var->data.original.transvar != NULL )
11118  {
11119  SCIP_CALL( SCIPvarChgBranchPriority(var->data.original.transvar, branchpriority) );
11120  }
11121  else
11122  var->branchpriority = branchpriority;
11123  break;
11124 
11125  case SCIP_VARSTATUS_COLUMN:
11126  case SCIP_VARSTATUS_LOOSE:
11127  case SCIP_VARSTATUS_FIXED:
11128  SCIP_CALL( varProcessChgBranchPriority(var, branchpriority) );
11129  break;
11130 
11132  assert(var->data.aggregate.var != NULL);
11133  SCIP_CALL( SCIPvarChgBranchPriority(var->data.aggregate.var, branchpriority) );
11134  break;
11135 
11137  assert(!var->donotmultaggr);
11138  for( v = 0; v < var->data.multaggr.nvars; ++v )
11139  {
11140  SCIP_CALL( SCIPvarChgBranchPriority(var->data.multaggr.vars[v], branchpriority) );
11141  }
11142  break;
11143 
11145  assert(var->negatedvar != NULL);
11147  assert(var->negatedvar->negatedvar == var);
11148  SCIP_CALL( SCIPvarChgBranchPriority(var->negatedvar, branchpriority) );
11149  break;
11150 
11151  default:
11152  SCIPerrorMessage("unknown variable status\n");
11153  SCIPABORT();
11154  return SCIP_ERROR; /*lint !e527*/
11155  }
11156 
11157  return SCIP_OKAY;
11158 }
11159 
11160 /** actually changes the branch direction of the variable and of all parent variables */
11161 static
11163  SCIP_VAR* var, /**< problem variable */
11164  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11165  )
11166 {
11167  SCIP_VAR* parentvar;
11168  int i;
11169 
11170  assert(var != NULL);
11171 
11172  SCIPdebugMessage("process changing branch direction of <%s> from %u to %d\n",
11173  var->name, var->branchdirection, branchdirection);
11174 
11175  if( branchdirection == (SCIP_BRANCHDIR)var->branchdirection )
11176  return SCIP_OKAY;
11177 
11178  /* change the branch direction */
11179  var->branchdirection = branchdirection; /*lint !e641*/
11180 
11181  /* process parent variables */
11182  for( i = 0; i < var->nparentvars; ++i )
11183  {
11184  parentvar = var->parentvars[i];
11185  assert(parentvar != NULL);
11186 
11187  switch( SCIPvarGetStatus(parentvar) )
11188  {
11190  /* do not change directions across the border between transformed and original problem */
11191  break;
11192 
11193  case SCIP_VARSTATUS_COLUMN:
11194  case SCIP_VARSTATUS_LOOSE:
11195  case SCIP_VARSTATUS_FIXED:
11197  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
11198  SCIPABORT();
11199  return SCIP_INVALIDDATA; /*lint !e527*/
11200 
11202  if( parentvar->data.aggregate.scalar > 0.0 )
11203  {
11204  SCIP_CALL( varProcessChgBranchDirection(parentvar, branchdirection) );
11205  }
11206  else
11207  {
11208  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11209  }
11210  break;
11211 
11213  SCIP_CALL( varProcessChgBranchDirection(parentvar, SCIPbranchdirOpposite(branchdirection)) );
11214  break;
11215 
11216  default:
11217  SCIPerrorMessage("unknown variable status\n");
11218  SCIPABORT();
11219  return SCIP_ERROR; /*lint !e527*/
11220  }
11221  }
11222 
11223  return SCIP_OKAY;
11224 }
11225 
11226 /** sets the branch direction of the variable; variables with higher branch direction are always preferred to variables
11227  * with lower direction in selection of branching variable
11228  */
11230  SCIP_VAR* var, /**< problem variable */
11231  SCIP_BRANCHDIR branchdirection /**< preferred branch direction of the variable (downwards, upwards, auto) */
11232  )
11233 {
11234  int v;
11235 
11236  assert(var != NULL);
11237 
11238  SCIPdebugMessage("changing branch direction of <%s> from %u to %d\n", var->name, var->branchdirection, branchdirection);
11239 
11240  if( (SCIP_BRANCHDIR)var->branchdirection == branchdirection )
11241  return SCIP_OKAY;
11242 
11243  /* change directions of attached variables */
11244  switch( SCIPvarGetStatus(var) )
11245  {
11247  if( var->data.original.transvar != NULL )
11248  {
11249  SCIP_CALL( SCIPvarChgBranchDirection(var->data.original.transvar, branchdirection) );
11250  }
11251  else
11252  var->branchdirection = branchdirection; /*lint !e641*/
11253  break;
11254 
11255  case SCIP_VARSTATUS_COLUMN:
11256  case SCIP_VARSTATUS_LOOSE:
11257  case SCIP_VARSTATUS_FIXED:
11258  SCIP_CALL( varProcessChgBranchDirection(var, branchdirection) );
11259  break;
11260 
11262  assert(var->data.aggregate.var != NULL);
11263  if( var->data.aggregate.scalar > 0.0 )
11264  {
11265  SCIP_CALL( SCIPvarChgBranchDirection(var->data.aggregate.var, branchdirection) );
11266  }
11267  else
11268  {
11270  }
11271  break;
11272 
11274  assert(!var->donotmultaggr);
11275  for( v = 0; v < var->data.multaggr.nvars; ++v )
11276  {
11277  /* only update branching direction of aggregation variables, if they don't have a preferred direction yet */
11278  assert(var->data.multaggr.vars[v] != NULL);
11280  {
11281  if( var->data.multaggr.scalars[v] > 0.0 )
11282  {
11283  SCIP_CALL( SCIPvarChgBranchDirection(var->data.multaggr.vars[v], branchdirection) );
11284  }
11285  else
11286  {
11288  }
11289  }
11290  }
11291  break;
11292 
11294  assert(var->negatedvar != NULL);
11296  assert(var->negatedvar->negatedvar == var);
11298  break;
11299 
11300  default:
11301  SCIPerrorMessage("unknown variable status\n");
11302  SCIPABORT();
11303  return SCIP_ERROR; /*lint !e527*/
11304  }
11305 
11306  return SCIP_OKAY;
11307 }
11308 
11309 /** compares the index of two variables, only active, fixed or negated variables are allowed, if a variable
11310  * is negated then the index of the corresponding active variable is taken, returns -1 if first is
11311  * smaller than, and +1 if first is greater than second variable index; returns 0 if both indices
11312  * are equal, which means both variables are equal
11313  */
11315  SCIP_VAR* var1, /**< first problem variable */
11316  SCIP_VAR* var2 /**< second problem variable */
11317  )
11318 {
11319  assert(var1 != NULL);
11320  assert(var2 != NULL);
11323 
11325  var1 = SCIPvarGetNegatedVar(var1);
11327  var2 = SCIPvarGetNegatedVar(var2);
11328 
11329  assert(var1 != NULL);
11330  assert(var2 != NULL);
11331 
11332  if( SCIPvarGetIndex(var1) < SCIPvarGetIndex(var2) )
11333  return -1;
11334  else if( SCIPvarGetIndex(var1) > SCIPvarGetIndex(var2) )
11335  return +1;
11336 
11337  assert(var1 == var2);
11338  return 0;
11339 }
11340 
11341 /** comparison method for sorting active and negated variables by non-decreasing index, active and negated
11342  * variables are handled as the same variables
11343  */
11344 SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
11346  return SCIPvarCompareActiveAndNegated((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11347 }
11348 
11349 /** compares the index of two variables, returns -1 if first is smaller than, and +1 if first is greater than second
11350  * variable index; returns 0 if both indices are equal, which means both variables are equal
11351  */
11352 int SCIPvarCompare(
11353  SCIP_VAR* var1, /**< first problem variable */
11354  SCIP_VAR* var2 /**< second problem variable */
11355  )
11356 {
11357  assert(var1 != NULL);
11358  assert(var2 != NULL);
11359 
11360  if( var1->index < var2->index )
11361  return -1;
11362  else if( var1->index > var2->index )
11363  return +1;
11364  else
11365  {
11366  assert(var1 == var2);
11367  return 0;
11368  }
11369 }
11370 
11371 /** comparison method for sorting variables by non-decreasing index */
11372 SCIP_DECL_SORTPTRCOMP(SCIPvarComp)
11374  return SCIPvarCompare((SCIP_VAR*)elem1, (SCIP_VAR*)elem2);
11375 }
11376 
11377 /** comparison method for sorting variables by non-decreasing objective coefficient */
11378 SCIP_DECL_SORTPTRCOMP(SCIPvarCompObj)
11380  SCIP_Real obj1;
11381  SCIP_Real obj2;
11382 
11383  obj1 = SCIPvarGetObj((SCIP_VAR*)elem1);
11384  obj2 = SCIPvarGetObj((SCIP_VAR*)elem2);
11385 
11386  if( obj1 < obj2 )
11387  return -1;
11388  else if( obj1 > obj2 )
11389  return +1;
11390  else
11391  return 0;
11392 }
11393 
11394 /** hash key retrieval function for variables */
11395 SCIP_DECL_HASHGETKEY(SCIPvarGetHashkey)
11396 { /*lint --e{715}*/
11397  return elem;
11398 }
11399 
11400 /** returns TRUE iff the indices of both variables are equal */
11401 SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
11402 { /*lint --e{715}*/
11403  if( key1 == key2 )
11404  return TRUE;
11405  return FALSE;
11406 }
11407 
11408 /** returns the hash value of the key */
11409 SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
11410 { /*lint --e{715}*/
11411  assert( SCIPvarGetIndex((SCIP_VAR*) key) >= 0 );
11412  return (unsigned int) SCIPvarGetIndex((SCIP_VAR*) key);
11413 }
11414 
11415 /** return for given variables all their active counterparts; all active variables will be pairwise different */
11417  SCIP_SET* set, /**< global SCIP settings */
11418  SCIP_VAR** vars, /**< variable array with given variables and as output all active
11419  * variables, if enough slots exist
11420  */
11421  int* nvars, /**< number of given variables, and as output number of active variables,
11422  * if enough slots exist
11423  */
11424  int varssize, /**< available slots in vars array */
11425  int* requiredsize /**< pointer to store the required array size for the active variables */
11426  )
11427 {
11428  SCIP_VAR** activevars;
11429  int nactivevars;
11430  int activevarssize;
11431 
11432  SCIP_VAR* var;
11433  int v;
11434 
11435  SCIP_VAR** tmpvars;
11436  SCIP_VAR** multvars;
11437  int tmpvarssize;
11438  int ntmpvars;
11439  int noldtmpvars;
11440  int nmultvars;
11441 
11442  assert(set != NULL);
11443  assert(nvars != NULL);
11444  assert(vars != NULL || *nvars == 0);
11445  assert(varssize >= *nvars);
11446  assert(requiredsize != NULL);
11447 
11448  *requiredsize = 0;
11449 
11450  if( *nvars == 0 )
11451  return SCIP_OKAY;
11452 
11453  nactivevars = 0;
11454  activevarssize = *nvars;
11455  ntmpvars = *nvars;
11456  tmpvarssize = *nvars;
11457 
11458  /* temporary memory */
11459  SCIP_CALL( SCIPsetAllocBufferArray(set, &activevars, activevarssize) );
11460  SCIP_CALL( SCIPsetDuplicateBufferArray(set, &tmpvars, vars, ntmpvars) );
11461 
11462  noldtmpvars = ntmpvars;
11463 
11464  /* sort all variables to combine equal variables easily */
11465  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11466  for( v = ntmpvars - 1; v > 0; --v )
11467  {
11468  /* combine same variables */
11469  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11470  {
11471  --ntmpvars;
11472  tmpvars[v] = tmpvars[ntmpvars];
11473  }
11474  }
11475  /* sort all variables again to combine equal variables later on */
11476  if( noldtmpvars > ntmpvars )
11477  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11478 
11479  /* collect for each variable the representation in active variables */
11480  while( ntmpvars >= 1 )
11481  {
11482  --ntmpvars;
11483  var = tmpvars[ntmpvars];
11484  assert( var != NULL );
11485 
11486  switch( SCIPvarGetStatus(var) )
11487  {
11489  if( var->data.original.transvar == NULL )
11490  {
11491  SCIPerrorMessage("original variable has no transformed variable attached\n");
11492  SCIPABORT();
11493  return SCIP_INVALIDDATA; /*lint !e527*/
11494  }
11495  tmpvars[ntmpvars] = var->data.original.transvar;
11496  ++ntmpvars;
11497  break;
11498 
11500  tmpvars[ntmpvars] = var->data.aggregate.var;
11501  ++ntmpvars;
11502  break;
11503 
11505  tmpvars[ntmpvars] = var->negatedvar;
11506  ++ntmpvars;
11507  break;
11508 
11509  case SCIP_VARSTATUS_LOOSE:
11510  case SCIP_VARSTATUS_COLUMN:
11511  /* check for space in temporary memory */
11512  if( nactivevars >= activevarssize )
11513  {
11514  activevarssize *= 2;
11515  SCIP_CALL( SCIPsetReallocBufferArray(set, &activevars, activevarssize) );
11516  assert(nactivevars < activevarssize);
11517  }
11518  activevars[nactivevars] = var;
11519  nactivevars++;
11520  break;
11521 
11523  /* x = a_1*y_1 + ... + a_n*y_n + c */
11524  nmultvars = var->data.multaggr.nvars;
11525  multvars = var->data.multaggr.vars;
11526 
11527  /* check for space in temporary memory */
11528  if( nmultvars + ntmpvars > tmpvarssize )
11529  {
11530  while( nmultvars + ntmpvars > tmpvarssize )
11531  tmpvarssize *= 2;
11532  SCIP_CALL( SCIPsetReallocBufferArray(set, &tmpvars, tmpvarssize) );
11533  assert(nmultvars + ntmpvars <= tmpvarssize);
11534  }
11535 
11536  /* copy all multi-aggregation variables into our working array */
11537  BMScopyMemoryArray(&tmpvars[ntmpvars], multvars, nmultvars); /*lint !e866*/
11538 
11539  /* get active, fixed or multi-aggregated corresponding variables for all new ones */
11540  SCIPvarsGetProbvar(&tmpvars[ntmpvars], nmultvars);
11541 
11542  ntmpvars += nmultvars;
11543  noldtmpvars = ntmpvars;
11544 
11545  /* sort all variables to combine equal variables easily */
11546  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11547  for( v = ntmpvars - 1; v > 0; --v )
11548  {
11549  /* combine same variables */
11550  if( SCIPvarCompare(tmpvars[v], tmpvars[v - 1]) == 0 )
11551  {
11552  --ntmpvars;
11553  tmpvars[v] = tmpvars[ntmpvars];
11554  }
11555  }
11556  /* sort all variables again to combine equal variables later on */
11557  if( noldtmpvars > ntmpvars )
11558  SCIPsortPtr((void**)tmpvars, SCIPvarComp, ntmpvars);
11559 
11560  break;
11561 
11562  case SCIP_VARSTATUS_FIXED:
11563  /* no need for memorizing fixed variables */
11564  break;
11565 
11566  default:
11567  SCIPerrorMessage("unknown variable status\n");
11568  SCIPABORT();
11569  return SCIP_INVALIDDATA; /*lint !e527*/
11570  }
11571  }
11572 
11573  /* sort variable array by variable index */
11574  SCIPsortPtr((void**)activevars, SCIPvarComp, nactivevars);
11575 
11576  /* eliminate duplicates and count required size */
11577  v = nactivevars - 1;
11578  while( v > 0 )
11579  {
11580  /* combine both variable since they are the same */
11581  if( SCIPvarCompare(activevars[v - 1], activevars[v]) == 0 )
11582  {
11583  --nactivevars;
11584  activevars[v] = activevars[nactivevars];
11585  }
11586  --v;
11587  }
11588  *requiredsize = nactivevars;
11589 
11590  if( varssize >= *requiredsize )
11591  {
11592  assert(vars != NULL);
11593 
11594  *nvars = *requiredsize;
11595  BMScopyMemoryArray(vars, activevars, nactivevars);
11596  }
11597 
11598  SCIPsetFreeBufferArray(set, &tmpvars);
11599  SCIPsetFreeBufferArray(set, &activevars);
11600 
11601  return SCIP_OKAY;
11602 }
11603 
11604 /** gets corresponding active, fixed, or multi-aggregated problem variables of given variables,
11605  * @note the content of the given array will/might change
11606  */
11607 void SCIPvarsGetProbvar(
11608  SCIP_VAR** vars, /**< array of problem variables */
11609  int nvars /**< number of variables */
11610  )
11611 {
11612  int v;
11613 
11614  assert(vars != NULL || nvars == 0);
11615 
11616  for( v = nvars - 1; v >= 0; --v )
11617  {
11618  assert(vars != NULL);
11619  assert(vars[v] != NULL);
11620 
11621  vars[v] = SCIPvarGetProbvar(vars[v]);
11622  assert(vars[v] != NULL);
11623  }
11624 }
11625 
11626 /** gets corresponding active, fixed, or multi-aggregated problem variable of a variable */
11628  SCIP_VAR* var /**< problem variable */
11629  )
11630 {
11631  SCIP_VAR* retvar;
11632 
11633  assert(var != NULL);
11634 
11635  retvar = var;
11636 
11637  SCIPdebugMessage("get problem variable of <%s>\n", var->name);
11638 
11639  while( TRUE ) /*lint !e716 */
11640  {
11641  assert(retvar != NULL);
11642 
11643  switch( SCIPvarGetStatus(retvar) )
11644  {
11646  if( retvar->data.original.transvar == NULL )
11647  {
11648  SCIPerrorMessage("original variable has no transformed variable attached\n");
11649  SCIPABORT();
11650  return NULL; /*lint !e527 */
11651  }
11652  retvar = retvar->data.original.transvar;
11653  break;
11654 
11655  case SCIP_VARSTATUS_LOOSE:
11656  case SCIP_VARSTATUS_COLUMN:
11657  case SCIP_VARSTATUS_FIXED:
11658  return retvar;
11659 
11661  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11662  if ( retvar->data.multaggr.nvars == 1 )
11663  retvar = retvar->data.multaggr.vars[0];
11664  else
11665  return retvar;
11666  break;
11667 
11669  retvar = retvar->data.aggregate.var;
11670  break;
11671 
11673  retvar = retvar->negatedvar;
11674  break;
11675 
11676  default:
11677  SCIPerrorMessage("unknown variable status\n");
11678  SCIPABORT();
11679  return NULL; /*lint !e527*/
11680  }
11681  }
11682 }
11683 
11684 /** gets corresponding active, fixed, or multi-aggregated problem variables of binary variables and updates the given
11685  * negation status of each variable
11686  */
11688  SCIP_VAR*** vars, /**< pointer to binary problem variables */
11689  SCIP_Bool** negatedarr, /**< pointer to corresponding array to update the negation status */
11690  int nvars /**< number of variables and values in vars and negated array */
11691  )
11692 {
11693  SCIP_VAR** var;
11694  SCIP_Bool* negated;
11695  int v;
11696 
11697  assert(vars != NULL);
11698  assert(*vars != NULL || nvars == 0);
11699  assert(negatedarr != NULL);
11700  assert(*negatedarr != NULL || nvars == 0);
11701 
11702  for( v = nvars - 1; v >= 0; --v )
11703  {
11704  var = &((*vars)[v]);
11705  negated = &((*negatedarr)[v]);
11706 
11707  /* get problem variable */
11708  SCIP_CALL( SCIPvarGetProbvarBinary(var, negated) );
11709  }
11710 
11711  return SCIP_OKAY;
11712 }
11713 
11714 
11715 /** gets corresponding active, fixed, or multi-aggregated problem variable of a binary variable and updates the given
11716  * negation status (this means you have to assign a value to SCIP_Bool negated before calling this method, usually
11717  * FALSE is used)
11718  */
11720  SCIP_VAR** var, /**< pointer to binary problem variable */
11721  SCIP_Bool* negated /**< pointer to update the negation status */
11722  )
11723 {
11725 #ifndef NDEBUG
11726  SCIP_Real constant = 0.0;
11727  SCIP_Bool orignegated;
11728 #endif
11729 
11730  assert(var != NULL);
11731  assert(*var != NULL);
11732  assert(negated != NULL);
11733  assert(SCIPvarIsBinary(*var));
11734 
11735 #ifndef NDEBUG
11736  orignegated = *negated;
11737 #endif
11738 
11739  while( !active && *var != NULL )
11740  {
11741  switch( SCIPvarGetStatus(*var) )
11742  {
11744  if( (*var)->data.original.transvar == NULL )
11745  return SCIP_OKAY;
11746  *var = (*var)->data.original.transvar;
11747  break;
11748 
11749  case SCIP_VARSTATUS_LOOSE:
11750  case SCIP_VARSTATUS_COLUMN:
11751  case SCIP_VARSTATUS_FIXED:
11752  active = TRUE;
11753  break;
11754 
11756  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11757  if ( (*var)->data.multaggr.nvars == 1 )
11758  {
11759  assert( (*var)->data.multaggr.vars != NULL );
11760  assert( (*var)->data.multaggr.scalars != NULL );
11761  assert( SCIPvarIsBinary((*var)->data.multaggr.vars[0]) );
11762  assert(!EPSZ((*var)->data.multaggr.scalars[0], 1e-06));
11763 
11764  /* if not all variables were fully propagated, it might happen that a variable is multi-aggregated to
11765  * another variable which needs to be fixed
11766  *
11767  * e.g. x = y - 1 => (x = 0 && y = 1)
11768  * e.g. x = y + 1 => (x = 1 && y = 0)
11769  *
11770  * is this special case we need to return the muti-aggregation
11771  */
11772  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)) )
11773  {
11774  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11775  }
11776  else
11777  {
11778  /* @note due to fixations, a multi-aggregation can have a constant of zero and a negative scalar or even
11779  * a scalar in absolute value unequal to one, in this case this aggregation variable needs to be
11780  * fixed to zero, but this should be done by another enforcement; so not depending on the scalar,
11781  * we will return the aggregated variable;
11782  */
11783  if( !EPSEQ(REALABS((*var)->data.multaggr.scalars[0]), 1.0, 1e-06) )
11784  {
11785  active = TRUE;
11786  break;
11787  }
11788 
11789  /* @note it may also happen that the constant is larger than 1 or smaller than 0, in that case the
11790  * aggregation variable needs to be fixed to one, but this should be done by another enforcement;
11791  * so if this is the case, we will return the aggregated variable
11792  */
11793  assert(EPSZ((*var)->data.multaggr.constant, 1e-06) || EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06)
11794  || EPSZ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1e-06)
11795  || EPSEQ((*var)->data.multaggr.constant + (*var)->data.multaggr.scalars[0], 1.0, 1e-06));
11796 
11797  if( !EPSZ((*var)->data.multaggr.constant, 1e-06) && !EPSEQ((*var)->data.multaggr.constant, 1.0, 1e-06) )
11798  {
11799  active = TRUE;
11800  break;
11801  }
11802 
11803  assert(EPSEQ((*var)->data.multaggr.scalars[0], 1.0, 1e-06) || EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11804 
11805  if( EPSZ((*var)->data.multaggr.constant, 1e-06) )
11806  {
11807  /* if the scalar is negative, either the aggregation variable is already fixed to zero or has at
11808  * least one uplock (that hopefully will enforce this fixation to zero); can it happen that this
11809  * variable itself is multi-aggregated again?
11810  */
11811  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06) ?
11812  ((SCIPvarGetUbGlobal((*var)->data.multaggr.vars[0]) < 0.5) ||
11813  SCIPvarGetNLocksUp((*var)->data.multaggr.vars[0]) > 0) : TRUE);
11814  }
11815  else
11816  {
11817  assert(EPSEQ((*var)->data.multaggr.scalars[0], -1.0, 1e-06));
11818 #ifndef NDEBUG
11819  constant += (*negated) != orignegated ? -1.0 : 1.0;
11820 #endif
11821 
11822  *negated = !(*negated);
11823  }
11824  *var = (*var)->data.multaggr.vars[0];
11825  break;
11826  }
11827  }
11828  active = TRUE;
11829  break;
11830 
11831  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
11832  assert((*var)->data.aggregate.var != NULL);
11833  assert(EPSEQ((*var)->data.aggregate.scalar, 1.0, 1e-06) || EPSEQ((*var)->data.aggregate.scalar, -1.0, 1e-06));
11834  assert(EPSLE((*var)->data.aggregate.var->glbdom.ub - (*var)->data.aggregate.var->glbdom.lb, 1.0, 1e-06));
11835 #ifndef NDEBUG
11836  constant += (*negated) != orignegated ? -(*var)->data.aggregate.constant : (*var)->data.aggregate.constant;
11837 #endif
11838 
11839  *negated = ((*var)->data.aggregate.scalar > 0.0) ? *negated : !(*negated);
11840  *var = (*var)->data.aggregate.var;
11841  break;
11842 
11843  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
11844  assert((*var)->negatedvar != NULL);
11845 #ifndef NDEBUG
11846  constant += (*negated) != orignegated ? -1.0 : 1.0;
11847 #endif
11848 
11849  *negated = !(*negated);
11850  *var = (*var)->negatedvar;
11851  break;
11852 
11853  default:
11854  SCIPerrorMessage("unknown variable status\n");
11855  return SCIP_INVALIDDATA;
11856  }
11857  }
11858  assert(active == (*var != NULL));
11859 
11860  if( active )
11861  {
11862  assert(SCIPvarIsBinary(*var));
11863  assert(EPSZ(constant, 1e-06) || EPSEQ(constant, 1.0, 1e-06));
11864  assert(EPSZ(constant, 1e-06) == ((*negated) == orignegated));
11865 
11866  return SCIP_OKAY;
11867  }
11868  else
11869  {
11870  SCIPerrorMessage("active variable path leads to NULL pointer\n");
11871  return SCIP_INVALIDDATA;
11872  }
11873 }
11874 
11875 /** transforms given variable, boundtype and bound to the corresponding active, fixed, or multi-aggregated variable
11876  * values
11877  */
11879  SCIP_VAR** var, /**< pointer to problem variable */
11880  SCIP_Real* bound, /**< pointer to bound value to transform */
11881  SCIP_BOUNDTYPE* boundtype /**< pointer to type of bound: lower or upper bound */
11882  )
11883 {
11884  assert(var != NULL);
11885  assert(*var != NULL);
11886  assert(bound != NULL);
11887  assert(boundtype != NULL);
11888 
11889  SCIPdebugMessage("get probvar bound %g of type %d of variable <%s>\n", *bound, *boundtype, (*var)->name);
11890 
11891  switch( SCIPvarGetStatus(*var) )
11892  {
11894  if( (*var)->data.original.transvar == NULL )
11895  {
11896  SCIPerrorMessage("original variable has no transformed variable attached\n");
11897  return SCIP_INVALIDDATA;
11898  }
11899  *var = (*var)->data.original.transvar;
11900  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11901  break;
11902 
11903  case SCIP_VARSTATUS_LOOSE:
11904  case SCIP_VARSTATUS_COLUMN:
11905  case SCIP_VARSTATUS_FIXED:
11906  break;
11907 
11909  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
11910  if ( (*var)->data.multaggr.nvars == 1 )
11911  {
11912  assert( (*var)->data.multaggr.vars != NULL );
11913  assert( (*var)->data.multaggr.scalars != NULL );
11914  assert( (*var)->data.multaggr.scalars[0] != 0.0 );
11915 
11916  (*bound) /= (*var)->data.multaggr.scalars[0];
11917  (*bound) -= (*var)->data.multaggr.constant/(*var)->data.multaggr.scalars[0];
11918  if ( (*var)->data.multaggr.scalars[0] < 0.0 )
11919  {
11920  if ( *boundtype == SCIP_BOUNDTYPE_LOWER )
11921  *boundtype = SCIP_BOUNDTYPE_UPPER;
11922  else
11923  *boundtype = SCIP_BOUNDTYPE_LOWER;
11924  }
11925  *var = (*var)->data.multaggr.vars[0];
11926  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11927  }
11928  break;
11929 
11930  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
11931  assert((*var)->data.aggregate.var != NULL);
11932  assert((*var)->data.aggregate.scalar != 0.0);
11933 
11934  (*bound) /= (*var)->data.aggregate.scalar;
11935  (*bound) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
11936  if( (*var)->data.aggregate.scalar < 0.0 )
11937  {
11938  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11939  *boundtype = SCIP_BOUNDTYPE_UPPER;
11940  else
11941  *boundtype = SCIP_BOUNDTYPE_LOWER;
11942  }
11943  *var = (*var)->data.aggregate.var;
11944  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11945  break;
11946 
11947  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
11948  assert((*var)->negatedvar != NULL);
11949  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
11950  assert((*var)->negatedvar->negatedvar == *var);
11951  (*bound) = (*var)->data.negate.constant - *bound;
11952  if( *boundtype == SCIP_BOUNDTYPE_LOWER )
11953  *boundtype = SCIP_BOUNDTYPE_UPPER;
11954  else
11955  *boundtype = SCIP_BOUNDTYPE_LOWER;
11956  *var = (*var)->negatedvar;
11957  SCIP_CALL( SCIPvarGetProbvarBound(var, bound, boundtype) );
11958  break;
11959 
11960  default:
11961  SCIPerrorMessage("unknown variable status\n");
11962  return SCIP_INVALIDDATA;
11963  }
11964 
11965  return SCIP_OKAY;
11966 }
11967 
11968 /** transforms given variable and domain hole to the corresponding active, fixed, or multi-aggregated variable
11969  * values
11970  */
11972  SCIP_VAR** var, /**< pointer to problem variable */
11973  SCIP_Real* left, /**< pointer to left bound of open interval in hole to transform */
11974  SCIP_Real* right /**< pointer to right bound of open interval in hole to transform */
11975  )
11976 {
11977  assert(var != NULL);
11978  assert(*var != NULL);
11979  assert(left != NULL);
11980  assert(right != NULL);
11981 
11982  SCIPdebugMessage("get probvar hole (%g,%g) of variable <%s>\n", *left, *right, (*var)->name);
11983 
11984  switch( SCIPvarGetStatus(*var) )
11985  {
11987  if( (*var)->data.original.transvar == NULL )
11988  {
11989  SCIPerrorMessage("original variable has no transformed variable attached\n");
11990  return SCIP_INVALIDDATA;
11991  }
11992  *var = (*var)->data.original.transvar;
11993  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
11994  break;
11995 
11996  case SCIP_VARSTATUS_LOOSE:
11997  case SCIP_VARSTATUS_COLUMN:
11998  case SCIP_VARSTATUS_FIXED:
12000  break;
12001 
12002  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = x/a - c/a */
12003  assert((*var)->data.aggregate.var != NULL);
12004  assert((*var)->data.aggregate.scalar != 0.0);
12005 
12006  /* scale back */
12007  (*left) /= (*var)->data.aggregate.scalar;
12008  (*right) /= (*var)->data.aggregate.scalar;
12009 
12010  /* shift back */
12011  (*left) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12012  (*right) -= (*var)->data.aggregate.constant/(*var)->data.aggregate.scalar;
12013 
12014  *var = (*var)->data.aggregate.var;
12015 
12016  /* check if the interval bounds have to swapped */
12017  if( (*var)->data.aggregate.scalar < 0.0 )
12018  {
12019  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12020  }
12021  else
12022  {
12023  SCIP_CALL( SCIPvarGetProbvarHole(var, left, right) );
12024  }
12025  break;
12026 
12027  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12028  assert((*var)->negatedvar != NULL);
12029  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12030  assert((*var)->negatedvar->negatedvar == *var);
12031 
12032  /* shift and scale back */
12033  (*left) = (*var)->data.negate.constant - (*left);
12034  (*right) = (*var)->data.negate.constant - (*right);
12035 
12036  *var = (*var)->negatedvar;
12037 
12038  /* through the negated variable the left and right interval bound have to swapped */
12039  SCIP_CALL( SCIPvarGetProbvarHole(var, right, left) );
12040  break;
12041 
12042  default:
12043  SCIPerrorMessage("unknown variable status\n");
12044  return SCIP_INVALIDDATA;
12045  }
12046 
12047  return SCIP_OKAY;
12048 }
12049 
12050 /** transforms given variable, scalar and constant to the corresponding active, fixed, or
12051  * multi-aggregated variable, scalar and constant; if the variable resolves to a fixed variable,
12052  * "scalar" will be 0.0 and the value of the sum will be stored in "constant"; a multi-aggregation
12053  * with only one active variable (this can happen due to fixings after the multi-aggregation),
12054  * is treated like an aggregation; if the multi-aggregation constant is infinite, "scalar" will be 0.0
12055  */
12057  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12058  SCIP_SET* set, /**< global SCIP settings */
12059  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12060  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12061  )
12062 {
12063  assert(var != NULL);
12064  assert(scalar != NULL);
12065  assert(constant != NULL);
12066 
12067  while( *var != NULL )
12068  {
12069  switch( SCIPvarGetStatus(*var) )
12070  {
12072  if( (*var)->data.original.transvar == NULL )
12073  {
12074  SCIPerrorMessage("original variable has no transformed variable attached\n");
12075  return SCIP_INVALIDDATA;
12076  }
12077  *var = (*var)->data.original.transvar;
12078  break;
12079 
12080  case SCIP_VARSTATUS_LOOSE:
12081  case SCIP_VARSTATUS_COLUMN:
12082  return SCIP_OKAY;
12083 
12084  case SCIP_VARSTATUS_FIXED: /* x = c' => a*x + c == (a*c' + c) */
12085  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12086  {
12087  if( SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)) )
12088  {
12089  assert(*scalar != 0.0);
12090  if( (*scalar) * (*var)->glbdom.lb > 0.0 )
12091  (*constant) = SCIPsetInfinity(set);
12092  else
12093  (*constant) = -SCIPsetInfinity(set);
12094  }
12095  else
12096  (*constant) += *scalar * (*var)->glbdom.lb;
12097  }
12098 #ifndef NDEBUG
12099  else
12100  {
12101  assert(!SCIPsetIsInfinity(set, (*constant)) || !((*scalar) * (*var)->glbdom.lb < 0.0 &&
12102  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12103  assert(!SCIPsetIsInfinity(set, -(*constant)) || !((*scalar) * (*var)->glbdom.lb > 0.0 &&
12104  (SCIPsetIsInfinity(set, (*var)->glbdom.lb) || SCIPsetIsInfinity(set, -((*var)->glbdom.lb)))));
12105  }
12106 #endif
12107  *scalar = 0.0;
12108  return SCIP_OKAY;
12109 
12111  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
12112  if ( (*var)->data.multaggr.nvars == 1 )
12113  {
12114  assert((*var)->data.multaggr.vars != NULL);
12115  assert((*var)->data.multaggr.scalars != NULL);
12116  assert((*var)->data.multaggr.vars[0] != NULL);
12117  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12118  {
12119  /* the multi-aggregation constant can be infinite, if one of the multi-aggregation variables
12120  * was fixed to +/-infinity; ensure that the constant is set to +/-infinity, too, and the scalar
12121  * is set to 0.0, because the multi-aggregated variable can be seen as fixed, too
12122  */
12123  if( SCIPsetIsInfinity(set, (*var)->data.multaggr.constant)
12124  || SCIPsetIsInfinity(set, -((*var)->data.multaggr.constant)) )
12125  {
12126  if( (*scalar) * (*var)->data.multaggr.constant > 0 )
12127  {
12128  assert(!SCIPsetIsInfinity(set, -(*constant)));
12129  (*constant) = SCIPsetInfinity(set);
12130  }
12131  else
12132  {
12133  assert(!SCIPsetIsInfinity(set, *constant));
12134  (*constant) = -SCIPsetInfinity(set);
12135  }
12136  (*scalar) = 0.0;
12137  }
12138  else
12139  (*constant) += *scalar * (*var)->data.multaggr.constant;
12140  }
12141  (*scalar) *= (*var)->data.multaggr.scalars[0];
12142  *var = (*var)->data.multaggr.vars[0];
12143  break;
12144  }
12145  return SCIP_OKAY;
12146 
12147  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
12148  assert((*var)->data.aggregate.var != NULL);
12149  assert(!SCIPsetIsInfinity(set, (*var)->data.aggregate.constant)
12150  && !SCIPsetIsInfinity(set, (*var)->data.aggregate.constant));
12151  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12152  (*constant) += *scalar * (*var)->data.aggregate.constant;
12153  (*scalar) *= (*var)->data.aggregate.scalar;
12154  *var = (*var)->data.aggregate.var;
12155  break;
12156 
12157  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
12158  assert((*var)->negatedvar != NULL);
12159  assert(SCIPvarGetStatus((*var)->negatedvar) != SCIP_VARSTATUS_NEGATED);
12160  assert((*var)->negatedvar->negatedvar == *var);
12161  assert(!SCIPsetIsInfinity(set, (*var)->data.negate.constant)
12162  && !SCIPsetIsInfinity(set, (*var)->data.negate.constant));
12163  if( !SCIPsetIsInfinity(set, (*constant)) && !SCIPsetIsInfinity(set, -(*constant)) )
12164  (*constant) += *scalar * (*var)->data.negate.constant;
12165  (*scalar) *= -1.0;
12166  *var = (*var)->negatedvar;
12167  break;
12168 
12169  default:
12170  SCIPerrorMessage("unknown variable status\n");
12171  SCIPABORT();
12172  return SCIP_INVALIDDATA; /*lint !e527*/
12173  }
12174  }
12175  *scalar = 0.0;
12176 
12177  return SCIP_OKAY;
12178 }
12179 
12180 /** retransforms given variable, scalar and constant to the corresponding original variable, scalar
12181  * and constant, if possible; if the retransformation is impossible, NULL is returned as variable
12182  */
12184  SCIP_VAR** var, /**< pointer to problem variable x in sum a*x + c */
12185  SCIP_Real* scalar, /**< pointer to scalar a in sum a*x + c */
12186  SCIP_Real* constant /**< pointer to constant c in sum a*x + c */
12187  )
12188 {
12189  SCIP_VAR* parentvar;
12190 
12191  assert(var != NULL);
12192  assert(*var != NULL);
12193  assert(scalar != NULL);
12194  assert(constant != NULL);
12195 
12196  while( !SCIPvarIsOriginal(*var) )
12197  {
12198  /* if the variable has no parent variables, it was generated during solving and has no corresponding original
12199  * var
12200  */
12201  if( (*var)->nparentvars == 0 )
12202  {
12203  /* negated variables do not need to have a parent variables, and negated variables can exist in original
12204  * space
12205  */
12207  ((*var)->negatedvar->nparentvars == 0 || (*var)->negatedvar->parentvars[0] != *var) )
12208  {
12209  *scalar *= -1.0;
12210  *constant -= (*var)->data.negate.constant * (*scalar);
12211  *var = (*var)->negatedvar;
12212 
12213  continue;
12214  }
12215  /* if the variables does not have any parent the variables was created during solving and has no original
12216  * counterpart
12217  */
12218  else
12219  {
12220  *var = NULL;
12221 
12222  return SCIP_OKAY;
12223  }
12224  }
12225 
12226  /* follow the link to the first parent variable */
12227  parentvar = (*var)->parentvars[0];
12228  assert(parentvar != NULL);
12229 
12230  switch( SCIPvarGetStatus(parentvar) )
12231  {
12233  break;
12234 
12235  case SCIP_VARSTATUS_COLUMN:
12236  case SCIP_VARSTATUS_LOOSE:
12237  case SCIP_VARSTATUS_FIXED:
12239  SCIPerrorMessage("column, loose, fixed or multi-aggregated variable cannot be the parent of a variable\n");
12240  return SCIP_INVALIDDATA;
12241 
12242  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + b -> y = (x-b)/a, s*y + c = (s/a)*x + c-b*s/a */
12243  assert(parentvar->data.aggregate.var == *var);
12244  assert(parentvar->data.aggregate.scalar != 0.0);
12245  *scalar /= parentvar->data.aggregate.scalar;
12246  *constant -= parentvar->data.aggregate.constant * (*scalar);
12247  break;
12248 
12249  case SCIP_VARSTATUS_NEGATED: /* x = b - y -> y = b - x, s*y + c = -s*x + c+b*s */
12250  assert(parentvar->negatedvar != NULL);
12251  assert(SCIPvarGetStatus(parentvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
12252  assert(parentvar->negatedvar->negatedvar == parentvar);
12253  *scalar *= -1.0;
12254  *constant -= parentvar->data.negate.constant * (*scalar);
12255  break;
12256 
12257  default:
12258  SCIPerrorMessage("unknown variable status\n");
12259  return SCIP_INVALIDDATA;
12260  }
12261 
12262  assert( parentvar != NULL );
12263  *var = parentvar;
12264  }
12265 
12266  return SCIP_OKAY;
12267 }
12268 
12269 /** returns whether the given variable is the direct counterpart of an original problem variable */
12271  SCIP_VAR* var /**< problem variable */
12272  )
12273 {
12274  SCIP_VAR* parentvar;
12275  assert(var != NULL);
12276 
12277  if( !SCIPvarIsTransformed(var) || var->nparentvars < 1 )
12278  return FALSE;
12279 
12280  assert(var->parentvars != NULL);
12281  parentvar = var->parentvars[0];
12282  assert(parentvar != NULL);
12283 
12284  /* we follow the aggregation tree to the root unless an original variable has been found - the first entries in the parentlist are candidates */
12285  while( parentvar->nparentvars >= 1 && SCIPvarGetStatus(parentvar) != SCIP_VARSTATUS_ORIGINAL )
12286  parentvar = parentvar->parentvars[0];
12287  assert( parentvar != NULL );
12288 
12289  return ( SCIPvarGetStatus(parentvar) == SCIP_VARSTATUS_ORIGINAL );
12290 }
12291 
12292 /** gets objective value of variable in current SCIP_LP; the value can be different from the objective value stored in
12293  * the variable's own data due to diving, that operate only on the LP without updating the variables
12294  */
12296  SCIP_VAR* var /**< problem variable */
12297  )
12298 {
12299  assert(var != NULL);
12300 
12301  /* get bounds of attached variables */
12302  switch( SCIPvarGetStatus(var) )
12303  {
12305  assert(var->data.original.transvar != NULL);
12306  return SCIPvarGetObjLP(var->data.original.transvar);
12307 
12308  case SCIP_VARSTATUS_COLUMN:
12309  assert(var->data.col != NULL);
12310  return SCIPcolGetObj(var->data.col);
12311 
12312  case SCIP_VARSTATUS_LOOSE:
12313  case SCIP_VARSTATUS_FIXED:
12314  return var->obj;
12315 
12316  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12317  assert(var->data.aggregate.var != NULL);
12318  return var->data.aggregate.scalar * SCIPvarGetObjLP(var->data.aggregate.var);
12319 
12321  SCIPerrorMessage("cannot get the objective value of a multiple aggregated variable\n");
12322  SCIPABORT();
12323  return 0.0; /*lint !e527*/
12324 
12325  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12326  assert(var->negatedvar != NULL);
12328  assert(var->negatedvar->negatedvar == var);
12329  return -SCIPvarGetObjLP(var->negatedvar);
12330 
12331  default:
12332  SCIPerrorMessage("unknown variable status\n");
12333  SCIPABORT();
12334  return 0.0; /*lint !e527*/
12335  }
12336 }
12337 
12338 /** gets lower bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12339  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12340  */
12342  SCIP_VAR* var, /**< problem variable */
12343  SCIP_SET* set /**< global SCIP settings */
12344  )
12345 {
12346  assert(var != NULL);
12347  assert(set != NULL);
12348  assert(var->scip == set->scip);
12349 
12350  /* get bounds of attached variables */
12351  switch( SCIPvarGetStatus(var) )
12352  {
12354  assert(var->data.original.transvar != NULL);
12355  return SCIPvarGetLbLP(var->data.original.transvar, set);
12356 
12357  case SCIP_VARSTATUS_COLUMN:
12358  assert(var->data.col != NULL);
12359  return SCIPcolGetLb(var->data.col);
12360 
12361  case SCIP_VARSTATUS_LOOSE:
12362  case SCIP_VARSTATUS_FIXED:
12363  return var->locdom.lb;
12364 
12365  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12366  assert(var->data.aggregate.var != NULL);
12367  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set)))
12368  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set))) )
12369  {
12370  return -SCIPsetInfinity(set);
12371  }
12372  else if( var->data.aggregate.scalar > 0.0 )
12373  {
12374  /* a > 0 -> get lower bound of y */
12375  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12376  }
12377  else if( var->data.aggregate.scalar < 0.0 )
12378  {
12379  /* a < 0 -> get upper bound of y */
12380  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12381  }
12382  else
12383  {
12384  SCIPerrorMessage("scalar is zero in aggregation\n");
12385  SCIPABORT();
12386  return SCIP_INVALID; /*lint !e527*/
12387  }
12388 
12390  /**@todo get the sides of the corresponding linear constraint */
12391  SCIPerrorMessage("getting the bounds of a multiple aggregated variable is not implemented yet\n");
12392  SCIPABORT();
12393  return SCIP_INVALID; /*lint !e527*/
12394 
12395  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12396  assert(var->negatedvar != NULL);
12398  assert(var->negatedvar->negatedvar == var);
12399  return var->data.negate.constant - SCIPvarGetUbLP(var->negatedvar, set);
12400 
12401  default:
12402  SCIPerrorMessage("unknown variable status\n");
12403  SCIPABORT();
12404  return SCIP_INVALID; /*lint !e527*/
12405  }
12406 }
12407 
12408 /** gets upper bound of variable in current SCIP_LP; the bound can be different from the bound stored in the variable's own
12409  * data due to diving or conflict analysis, that operate only on the LP without updating the variables
12410  */
12412  SCIP_VAR* var, /**< problem variable */
12413  SCIP_SET* set /**< global SCIP settings */
12414  )
12415 {
12416  assert(var != NULL);
12417  assert(set != NULL);
12418  assert(var->scip == set->scip);
12419 
12420  /* get bounds of attached variables */
12421  switch( SCIPvarGetStatus(var) )
12422  {
12424  assert(var->data.original.transvar != NULL);
12425  return SCIPvarGetUbLP(var->data.original.transvar, set);
12426 
12427  case SCIP_VARSTATUS_COLUMN:
12428  assert(var->data.col != NULL);
12429  return SCIPcolGetUb(var->data.col);
12430 
12431  case SCIP_VARSTATUS_LOOSE:
12432  case SCIP_VARSTATUS_FIXED:
12433  return var->locdom.ub;
12434 
12435  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
12436  assert(var->data.aggregate.var != NULL);
12437  if( (var->data.aggregate.scalar > 0.0 && SCIPsetIsInfinity(set, SCIPvarGetUbLP(var->data.aggregate.var, set)))
12438  || (var->data.aggregate.scalar < 0.0 && SCIPsetIsInfinity(set, -SCIPvarGetLbLP(var->data.aggregate.var, set))) )
12439  {
12440  return SCIPsetInfinity(set);
12441  }
12442  if( var->data.aggregate.scalar > 0.0 )
12443  {
12444  /* a > 0 -> get upper bound of y */
12445  return var->data.aggregate.scalar * SCIPvarGetUbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12446  }
12447  else if( var->data.aggregate.scalar < 0.0 )
12448  {
12449  /* a < 0 -> get lower bound of y */
12450  return var->data.aggregate.scalar * SCIPvarGetLbLP(var->data.aggregate.var, set) + var->data.aggregate.constant;
12451  }
12452  else
12453  {
12454  SCIPerrorMessage("scalar is zero in aggregation\n");
12455  SCIPABORT();
12456  return SCIP_INVALID; /*lint !e527*/
12457  }
12458 
12460  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
12461  SCIPABORT();
12462  return SCIP_INVALID; /*lint !e527*/
12463 
12464  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12465  assert(var->negatedvar != NULL);
12467  assert(var->negatedvar->negatedvar == var);
12468  return var->data.negate.constant - SCIPvarGetLbLP(var->negatedvar, set);
12469 
12470  default:
12471  SCIPerrorMessage("unknown variable status\n");
12472  SCIPABORT();
12473  return SCIP_INVALID; /*lint !e527*/
12474  }
12475 }
12476 
12477 /** gets primal LP solution value of variable */
12479  SCIP_VAR* var /**< problem variable */
12480  )
12481 {
12482  assert(var != NULL);
12483 
12484  switch( SCIPvarGetStatus(var) )
12485  {
12487  if( var->data.original.transvar == NULL )
12488  return SCIP_INVALID;
12489  return SCIPvarGetLPSol(var->data.original.transvar);
12490 
12491  case SCIP_VARSTATUS_LOOSE:
12492  return SCIPvarGetBestBoundLocal(var);
12493 
12494  case SCIP_VARSTATUS_COLUMN:
12495  assert(var->data.col != NULL);
12496  return SCIPcolGetPrimsol(var->data.col);
12497 
12498  case SCIP_VARSTATUS_FIXED:
12499  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12500  return var->locdom.lb;
12501 
12503  {
12504  SCIP_Real lpsolval;
12505 
12506  assert(var->data.aggregate.var != NULL);
12507  lpsolval = SCIPvarGetLPSol(var->data.aggregate.var);
12508 
12509  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12510  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12511  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12512  * (or is called by) a public interface method; instead, we only assert that values are finite
12513  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12514  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12515  */
12516  assert(lpsolval > -SCIP_DEFAULT_INFINITY);
12517  assert(lpsolval < +SCIP_DEFAULT_INFINITY);
12518  return var->data.aggregate.scalar * lpsolval + var->data.aggregate.constant;
12519  }
12521  {
12522  SCIP_Real primsol;
12523  int i;
12524 
12525  assert(!var->donotmultaggr);
12526  assert(var->data.multaggr.vars != NULL);
12527  assert(var->data.multaggr.scalars != NULL);
12528  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12529  * assert(var->data.multaggr.nvars >= 2);
12530  */
12531  primsol = var->data.multaggr.constant;
12532  for( i = 0; i < var->data.multaggr.nvars; ++i )
12533  primsol += var->data.multaggr.scalars[i] * SCIPvarGetLPSol(var->data.multaggr.vars[i]);
12534  return primsol;
12535  }
12536  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12537  assert(var->negatedvar != NULL);
12539  assert(var->negatedvar->negatedvar == var);
12540  return var->data.negate.constant - SCIPvarGetLPSol(var->negatedvar);
12541 
12542  default:
12543  SCIPerrorMessage("unknown variable status\n");
12544  SCIPABORT();
12545  return SCIP_INVALID; /*lint !e527*/
12546  }
12547 }
12548 
12549 /** gets primal NLP solution value of variable */
12551  SCIP_VAR* var /**< problem variable */
12552  )
12553 {
12554  SCIP_Real solval;
12555  int i;
12556 
12557  assert(var != NULL);
12558 
12559  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
12560  switch( SCIPvarGetStatus(var) )
12561  {
12563  return SCIPvarGetNLPSol(var->data.original.transvar);
12564 
12565  case SCIP_VARSTATUS_LOOSE:
12566  case SCIP_VARSTATUS_COLUMN:
12567  return var->nlpsol;
12568 
12569  case SCIP_VARSTATUS_FIXED:
12570  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
12571  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
12572  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
12573  return SCIPvarGetLbGlobal(var);
12574 
12575  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
12576  solval = SCIPvarGetNLPSol(var->data.aggregate.var);
12577  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
12578 
12580  solval = var->data.multaggr.constant;
12581  for( i = 0; i < var->data.multaggr.nvars; ++i )
12582  solval += var->data.multaggr.scalars[i] * SCIPvarGetNLPSol(var->data.multaggr.vars[i]);
12583  return solval;
12584 
12586  solval = SCIPvarGetNLPSol(var->negatedvar);
12587  return var->data.negate.constant - solval;
12588 
12589  default:
12590  SCIPerrorMessage("unknown variable status\n");
12591  SCIPABORT();
12592  return SCIP_INVALID; /*lint !e527*/
12593  }
12594 }
12595 
12596 /** gets pseudo solution value of variable at current node */
12597 static
12599  SCIP_VAR* var /**< problem variable */
12600  )
12601 {
12602  SCIP_Real pseudosol;
12603  int i;
12604 
12605  assert(var != NULL);
12606 
12607  switch( SCIPvarGetStatus(var) )
12608  {
12610  if( var->data.original.transvar == NULL )
12611  return SCIP_INVALID;
12613 
12614  case SCIP_VARSTATUS_LOOSE:
12615  case SCIP_VARSTATUS_COLUMN:
12616  return SCIPvarGetBestBoundLocal(var);
12617 
12618  case SCIP_VARSTATUS_FIXED:
12619  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12620  return var->locdom.lb;
12621 
12623  {
12624  SCIP_Real pseudosolval;
12625  assert(var->data.aggregate.var != NULL);
12626  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12627  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12628  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12629  * (or is called by) a public interface method; instead, we only assert that values are finite
12630  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12631  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12632  */
12633  pseudosolval = SCIPvarGetPseudoSol(var->data.aggregate.var);
12634  assert(pseudosolval > -SCIP_DEFAULT_INFINITY);
12635  assert(pseudosolval < +SCIP_DEFAULT_INFINITY);
12636  return var->data.aggregate.scalar * pseudosolval + var->data.aggregate.constant;
12637  }
12639  assert(!var->donotmultaggr);
12640  assert(var->data.multaggr.vars != NULL);
12641  assert(var->data.multaggr.scalars != NULL);
12642  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12643  * assert(var->data.multaggr.nvars >= 2);
12644  */
12645  pseudosol = var->data.multaggr.constant;
12646  for( i = 0; i < var->data.multaggr.nvars; ++i )
12647  pseudosol += var->data.multaggr.scalars[i] * SCIPvarGetPseudoSol(var->data.multaggr.vars[i]);
12648  return pseudosol;
12649 
12650  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12651  assert(var->negatedvar != NULL);
12653  assert(var->negatedvar->negatedvar == var);
12654  return var->data.negate.constant - SCIPvarGetPseudoSol(var->negatedvar);
12655 
12656  default:
12657  SCIPerrorMessage("unknown variable status\n");
12658  SCIPABORT();
12659  return SCIP_INVALID; /*lint !e527*/
12660  }
12661 }
12662 
12663 /** gets current LP or pseudo solution value of variable */
12665  SCIP_VAR* var, /**< problem variable */
12666  SCIP_Bool getlpval /**< should the LP solution value be returned? */
12667  )
12668 {
12669  if( getlpval )
12670  return SCIPvarGetLPSol(var);
12671  else
12672  return SCIPvarGetPseudoSol(var);
12673 }
12674 
12675 /** remembers the current solution as root solution in the problem variables */
12676 void SCIPvarStoreRootSol(
12677  SCIP_VAR* var, /**< problem variable */
12678  SCIP_Bool roothaslp /**< is the root solution from LP? */
12679  )
12680 {
12681  assert(var != NULL);
12682 
12683  var->rootsol = SCIPvarGetSol(var, roothaslp);
12684 }
12685 
12686 /** updates the current solution as best root solution of the given variable if it is better */
12688  SCIP_VAR* var, /**< problem variable */
12689  SCIP_SET* set, /**< global SCIP settings */
12690  SCIP_Real rootsol, /**< root solution value */
12691  SCIP_Real rootredcost, /**< root reduced cost */
12692  SCIP_Real rootlpobjval /**< objective value of the root LP */
12693  )
12694 {
12695  assert(var != NULL);
12696  assert(set != NULL);
12697  assert(var->scip == set->scip);
12698 
12699  /* if reduced cost are zero nothing to update */
12700  if( SCIPsetIsDualfeasZero(set, rootredcost) )
12701  return;
12702 
12703  /* check if we have already a best combination stored */
12704  if( !SCIPsetIsDualfeasZero(set, var->bestrootredcost) )
12705  {
12706  SCIP_Real currcutoffbound;
12707  SCIP_Real cutoffbound;
12708  SCIP_Real bound;
12709 
12710  /* compute the cutoff bound which would improve the corresponding bound with the current stored root solution,
12711  * root reduced cost, and root LP objective value combination
12712  */
12713  if( var->bestrootredcost > 0.0 )
12714  bound = SCIPvarGetUbGlobal(var);
12715  else
12716  bound = SCIPvarGetLbGlobal(var);
12717 
12718  currcutoffbound = (bound - var->bestrootsol) * var->bestrootredcost + var->bestrootlpobjval;
12719 
12720  /* compute the cutoff bound which would improve the corresponding bound with new root solution, root reduced
12721  * cost, and root LP objective value combination
12722  */
12723  if( rootredcost > 0.0 )
12724  bound = SCIPvarGetUbGlobal(var);
12725  else
12726  bound = SCIPvarGetLbGlobal(var);
12727 
12728  cutoffbound = (bound - rootsol) * rootredcost + rootlpobjval;
12729 
12730  /* check if an improving root solution, root reduced cost, and root LP objective value is at hand */
12731  if( cutoffbound > currcutoffbound )
12732  {
12733  SCIPsetDebugMsg(set, "-> <%s> update potential cutoff bound <%g> -> <%g>\n",
12734  SCIPvarGetName(var), currcutoffbound, cutoffbound);
12735 
12736  var->bestrootsol = rootsol;
12737  var->bestrootredcost = rootredcost;
12738  var->bestrootlpobjval = rootlpobjval;
12739  }
12740  }
12741  else
12742  {
12743  SCIPsetDebugMsg(set, "-> <%s> initialize best root reduced cost information\n", SCIPvarGetName(var));
12744  SCIPsetDebugMsg(set, " -> rootsol <%g>\n", rootsol);
12745  SCIPsetDebugMsg(set, " -> rootredcost <%g>\n", rootredcost);
12746  SCIPsetDebugMsg(set, " -> rootlpobjval <%g>\n", rootlpobjval);
12747 
12748  var->bestrootsol = rootsol;
12749  var->bestrootredcost = rootredcost;
12750  var->bestrootlpobjval = rootlpobjval;
12751  }
12752 }
12753 
12754 /** returns the solution of the variable in the last root node's relaxation, if the root relaxation is not yet
12755  * completely solved, zero is returned
12756  */
12758  SCIP_VAR* var /**< problem variable */
12759  )
12760 {
12761  SCIP_Real rootsol;
12762  int i;
12763 
12764  assert(var != NULL);
12765 
12766  switch( SCIPvarGetStatus(var) )
12767  {
12769  if( var->data.original.transvar == NULL )
12770  return 0.0;
12771  return SCIPvarGetRootSol(var->data.original.transvar);
12772 
12773  case SCIP_VARSTATUS_LOOSE:
12774  case SCIP_VARSTATUS_COLUMN:
12775  return var->rootsol;
12776 
12777  case SCIP_VARSTATUS_FIXED:
12778  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
12779  return var->locdom.lb;
12780 
12782  assert(var->data.aggregate.var != NULL);
12783  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
12784  * corresponding infinity value instead of performing an arithmetical transformation (compare method
12785  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
12786  * (or is called by) a public interface method; instead, we only assert that values are finite
12787  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
12788  * positives and negatives if the parameter <numerics/infinity> is modified by the user
12789  */
12793 
12795  assert(!var->donotmultaggr);
12796  assert(var->data.multaggr.vars != NULL);
12797  assert(var->data.multaggr.scalars != NULL);
12798  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
12799  * assert(var->data.multaggr.nvars >= 2);
12800  */
12801  rootsol = var->data.multaggr.constant;
12802  for( i = 0; i < var->data.multaggr.nvars; ++i )
12803  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetRootSol(var->data.multaggr.vars[i]);
12804  return rootsol;
12805 
12806  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
12807  assert(var->negatedvar != NULL);
12809  assert(var->negatedvar->negatedvar == var);
12810  return var->data.negate.constant - SCIPvarGetRootSol(var->negatedvar);
12811 
12812  default:
12813  SCIPerrorMessage("unknown variable status\n");
12814  SCIPABORT();
12815  return SCIP_INVALID; /*lint !e527*/
12816  }
12817 }
12818 
12819 /** returns for given variable the reduced cost */
12820 static
12822  SCIP_VAR* var, /**< problem variable */
12823  SCIP_SET* set, /**< global SCIP settings */
12824  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12825  SCIP_STAT* stat, /**< problem statistics */
12826  SCIP_LP* lp /**< current LP data */
12827  )
12828 {
12830  {
12831  SCIP_COL* col;
12832  SCIP_Real primsol;
12833  SCIP_BASESTAT basestat;
12834  SCIP_Bool lpissolbasic;
12835 
12836  col = SCIPvarGetCol(var);
12837  assert(col != NULL);
12838 
12839  basestat = SCIPcolGetBasisStatus(col);
12840  lpissolbasic = SCIPlpIsSolBasic(lp);
12841  primsol = SCIPcolGetPrimsol(col);
12842 
12843  if( (lpissolbasic && (basestat == SCIP_BASESTAT_LOWER || basestat == SCIP_BASESTAT_UPPER)) ||
12844  (!lpissolbasic && (SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol) || SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol))) )
12845  {
12846  SCIP_Real redcost = SCIPcolGetRedcost(col, stat, lp);
12847 
12848  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)) ||
12849  (lpissolbasic && basestat == SCIP_BASESTAT_LOWER)) ? (!SCIPsetIsDualfeasNegative(set, redcost) ||
12851  assert(((!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)) ||
12852  (lpissolbasic && basestat == SCIP_BASESTAT_UPPER)) ? (!SCIPsetIsDualfeasPositive(set, redcost) ||
12853  SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), SCIPvarGetUbLocal(var))) : TRUE);
12854 
12855  if( (varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_LOWER) ||
12856  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetLbLocal(var), primsol)))) ||
12857  (!varfixing && ((lpissolbasic && basestat == SCIP_BASESTAT_UPPER) ||
12858  (!lpissolbasic && SCIPsetIsFeasEQ(set, SCIPvarGetUbLocal(var), primsol)))) )
12859  return redcost;
12860  else
12861  return 0.0;
12862  }
12863 
12864  return 0.0;
12865  }
12866 
12867  return 0.0;
12868 }
12869 
12870 #define MAX_CLIQUELENGTH 50
12871 /** returns for the given binary variable the reduced cost which are given by the variable itself and its implication if
12872  * the binary variable is fixed to the given value
12873  */
12875  SCIP_VAR* var, /**< problem variable */
12876  SCIP_SET* set, /**< global SCIP settings */
12877  SCIP_Bool varfixing, /**< FALSE if for x == 0, TRUE for x == 1 */
12878  SCIP_STAT* stat, /**< problem statistics */
12879  SCIP_PROB* prob, /**< transformed problem, or NULL */
12880  SCIP_LP* lp /**< current LP data */
12881  )
12882 {
12883  SCIP_Real implredcost;
12884  int ncliques;
12885  int nvars;
12886 
12887  assert(SCIPvarIsBinary(var));
12888  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
12889 
12890  /* get reduced cost of given variable */
12891  implredcost = getImplVarRedcost(var, set, varfixing, stat, lp);
12892 
12893 #ifdef SCIP_MORE_DEBUG
12894  SCIPsetDebugMsg(set, "variable <%s> itself has reduced cost of %g\n", SCIPvarGetName(var), implredcost);
12895 #endif
12896 
12897  /* the following algorithm is expensive */
12898  ncliques = SCIPvarGetNCliques(var, varfixing);
12899 
12900  if( ncliques > 0 )
12901  {
12902  SCIP_CLIQUE** cliques;
12903  SCIP_CLIQUE* clique;
12904  SCIP_VAR** clqvars;
12905  SCIP_VAR** probvars;
12906  SCIP_VAR* clqvar;
12907  SCIP_Bool* clqvalues;
12908  int* entries;
12909  int* ids;
12910  SCIP_Real redcost;
12911  SCIP_Bool cleanedup;
12912  int nclqvars;
12913  int nentries;
12914  int nids;
12915  int id;
12916  int c;
12917  int v;
12918 
12919  assert(prob != NULL);
12920  assert(SCIPprobIsTransformed(prob));
12921 
12922  nentries = SCIPprobGetNVars(prob) - SCIPprobGetNContVars(prob) + 1;
12923 
12924  SCIP_CALL_ABORT( SCIPsetAllocBufferArray(set, &ids, nentries) );
12925  nids = 0;
12926  SCIP_CALL_ABORT( SCIPsetAllocCleanBufferArray(set, &entries, nentries) );
12927 
12928  cliques = SCIPvarGetCliques(var, varfixing);
12929  assert(cliques != NULL);
12930 
12931  for( c = ncliques - 1; c >= 0; --c )
12932  {
12933  clique = cliques[c];
12934  assert(clique != NULL);
12935  nclqvars = SCIPcliqueGetNVars(clique);
12936  assert(nclqvars > 0);
12937 
12938  if( nclqvars > MAX_CLIQUELENGTH )
12939  continue;
12940 
12941  clqvars = SCIPcliqueGetVars(clique);
12942  clqvalues = SCIPcliqueGetValues(clique);
12943  assert(clqvars != NULL);
12944  assert(clqvalues != NULL);
12945 
12946  cleanedup = SCIPcliqueIsCleanedUp(clique);
12947 
12948  for( v = nclqvars - 1; v >= 0; --v )
12949  {
12950  clqvar = clqvars[v];
12951  assert(clqvar != NULL);
12952 
12953  /* ignore binary variable which are fixed */
12954  if( clqvar != var && (cleanedup || SCIPvarIsActive(clqvar)) &&
12955  (SCIPvarGetLbLocal(clqvar) < 0.5 && SCIPvarGetUbLocal(clqvar) > 0.5) )
12956  {
12957  int probindex = SCIPvarGetProbindex(clqvar) + 1;
12958  assert(0 < probindex && probindex < nentries);
12959 
12960 #if 0
12961  /* check that the variable was not yet visited or does not appear with two contradicting implications, ->
12962  * can appear since there is no guarantee that all these infeasible bounds were found
12963  */
12964  assert(!entries[probindex] || entries[probindex] == (clqvalues[v] ? probindex : -probindex));
12965 #endif
12966  if( entries[probindex] == 0 )
12967  {
12968  ids[nids] = probindex;
12969  ++nids;
12970 
12971  /* mark variable as visited */
12972  entries[probindex] = (clqvalues[v] ? probindex : -probindex);
12973  }
12974  }
12975  }
12976  }
12977 
12978  probvars = SCIPprobGetVars(prob);
12979  assert(probvars != NULL);
12980 
12981  /* add all implied reduced cost */
12982  for( v = nids - 1; v >= 0; --v )
12983  {
12984  id = ids[v];
12985  assert(0 < id && id < nentries);
12986  assert(entries[id] != 0);
12987  assert(probvars[id - 1] != NULL);
12988  assert(SCIPvarIsActive(probvars[id - 1]));
12989  assert(SCIPvarIsBinary(probvars[id - 1]));
12990  assert(SCIPvarGetLbLocal(probvars[id - 1]) < 0.5 && SCIPvarGetUbLocal(probvars[id - 1]) > 0.5);
12991 
12992  if( (entries[id] > 0) != varfixing )
12993  redcost = getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12994  else
12995  redcost = -getImplVarRedcost(probvars[id - 1], set, (entries[id] < 0), stat, lp);
12996 
12997  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
12998  implredcost += redcost;
12999 
13000  /* reset entries clear buffer array */
13001  entries[id] = 0;
13002  }
13003 
13004  SCIPsetFreeCleanBufferArray(set, &entries);
13005  SCIPsetFreeBufferArray(set, &ids);
13006  }
13007 
13008 #ifdef SCIP_MORE_DEBUG
13009  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) has implied reduced cost of %g\n", SCIPvarGetName(var), ncliques,
13010  implredcost);
13011 #endif
13012 
13013  /* collect non-binary implication information */
13014  nvars = SCIPimplicsGetNImpls(var->implics, varfixing);
13015 
13016  if( nvars > 0 )
13017  {
13018  SCIP_VAR** vars;
13019  SCIP_VAR* implvar;
13020  SCIP_COL* col;
13021  SCIP_Real* bounds;
13022  SCIP_BOUNDTYPE* boundtypes;
13023  SCIP_Real redcost;
13024  SCIP_Real lb;
13025  SCIP_Real ub;
13026  SCIP_Bool lpissolbasic;
13027  int v;
13028 
13029  vars = SCIPimplicsGetVars(var->implics, varfixing);
13030  boundtypes = SCIPimplicsGetTypes(var->implics, varfixing);
13031  bounds = SCIPimplicsGetBounds(var->implics, varfixing);
13032  lpissolbasic = SCIPlpIsSolBasic(lp);
13033 
13034  for( v = nvars - 1; v >= 0; --v )
13035  {
13036  implvar = vars[v];
13037  assert(implvar != NULL);
13038 
13039  lb = SCIPvarGetLbLocal(implvar);
13040  ub = SCIPvarGetUbLocal(implvar);
13041 
13042  /* ignore binary variable which are fixed or not of column status */
13043  if( SCIPvarGetStatus(implvar) != SCIP_VARSTATUS_COLUMN || SCIPsetIsFeasEQ(set, lb, ub) )
13044  continue;
13045 
13046  col = SCIPvarGetCol(implvar);
13047  assert(col != NULL);
13048  redcost = 0.0;
13049 
13050  /* solved lp with basis information or not? */
13051  if( lpissolbasic )
13052  {
13053  SCIP_BASESTAT basestat = SCIPcolGetBasisStatus(col);
13054 
13055  /* check if the implication is not not yet applied */
13056  if( basestat == SCIP_BASESTAT_LOWER && boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasGT(set, bounds[v], lb) )
13057  {
13058  redcost = SCIPcolGetRedcost(col, stat, lp);
13059  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13060 
13061  if( !varfixing )
13062  redcost *= (lb - bounds[v]);
13063  else
13064  redcost *= (bounds[v] - lb);
13065  }
13066  else if( basestat == SCIP_BASESTAT_UPPER && boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasLT(set, bounds[v], ub) )
13067  {
13068  redcost = SCIPcolGetRedcost(col, stat, lp);
13069  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13070 
13071  if( varfixing )
13072  redcost *= (bounds[v] - ub);
13073  else
13074  redcost *= (ub - bounds[v]);
13075  }
13076  }
13077  else
13078  {
13079  SCIP_Real primsol = SCIPcolGetPrimsol(col);
13080 
13081  /* check if the implication is not not yet applied */
13082  if( boundtypes[v] == SCIP_BOUNDTYPE_LOWER && SCIPsetIsFeasEQ(set, lb, primsol) && SCIPsetIsFeasGT(set, bounds[v], lb) )
13083  {
13084  redcost = SCIPcolGetRedcost(col, stat, lp);
13085  assert(!SCIPsetIsDualfeasNegative(set, redcost));
13086 
13087  if( varfixing )
13088  redcost *= (lb - bounds[v]);
13089  else
13090  redcost *= (bounds[v] - lb);
13091  }
13092  else if( boundtypes[v] == SCIP_BOUNDTYPE_UPPER && SCIPsetIsFeasEQ(set, ub, primsol) && SCIPsetIsFeasLT(set, bounds[v], ub) )
13093  {
13094  redcost = SCIPcolGetRedcost(col, stat, lp);
13095  assert(!SCIPsetIsDualfeasPositive(set, redcost));
13096 
13097  if( varfixing )
13098  redcost *= (bounds[v] - ub);
13099  else
13100  redcost *= (ub - bounds[v]);
13101  }
13102  }
13103 
13104  /* improve implied reduced cost */
13105  if( (varfixing && SCIPsetIsDualfeasPositive(set, redcost)) || (!varfixing && SCIPsetIsDualfeasNegative(set, redcost)) )
13106  implredcost += redcost;
13107  }
13108  }
13109 
13110 #ifdef SCIP_MORE_DEBUG
13111  SCIPsetDebugMsg(set, "variable <%s> incl. cliques (%d) and implications (%d) has implied reduced cost of %g\n",
13112  SCIPvarGetName(var), ncliques, nvars, implredcost);
13113 #endif
13114 
13115  return implredcost;
13116 }
13117 
13118 /** returns the best solution (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation, if
13119  * the root relaxation is not yet completely solved, zero is returned
13120  */
13122  SCIP_VAR* var /**< problem variable */
13123  )
13124 {
13125  SCIP_Real rootsol;
13126  int i;
13127 
13128  assert(var != NULL);
13129 
13130  switch( SCIPvarGetStatus(var) )
13131  {
13133  if( var->data.original.transvar == NULL )
13134  return 0.0;
13136 
13137  case SCIP_VARSTATUS_LOOSE:
13138  case SCIP_VARSTATUS_COLUMN:
13139  return var->bestrootsol;
13140 
13141  case SCIP_VARSTATUS_FIXED:
13142  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13143  return var->locdom.lb;
13144 
13146  assert(var->data.aggregate.var != NULL);
13147  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
13148  * corresponding infinity value instead of performing an arithmetical transformation (compare method
13149  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
13150  * (or is called by) a public interface method; instead, we only assert that values are finite
13151  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
13152  * positives and negatives if the parameter <numerics/infinity> is modified by the user
13153  */
13157 
13159  assert(!var->donotmultaggr);
13160  assert(var->data.multaggr.vars != NULL);
13161  assert(var->data.multaggr.scalars != NULL);
13162  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13163  * assert(var->data.multaggr.nvars >= 2);
13164  */
13165  rootsol = var->data.multaggr.constant;
13166  for( i = 0; i < var->data.multaggr.nvars; ++i )
13167  rootsol += var->data.multaggr.scalars[i] * SCIPvarGetBestRootSol(var->data.multaggr.vars[i]);
13168  return rootsol;
13169 
13170  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13171  assert(var->negatedvar != NULL);
13173  assert(var->negatedvar->negatedvar == var);
13174  return var->data.negate.constant - SCIPvarGetBestRootSol(var->negatedvar);
13175 
13176  default:
13177  SCIPerrorMessage("unknown variable status\n");
13178  SCIPABORT();
13179  return 0.0; /*lint !e527*/
13180  }
13181 }
13182 
13183 /** returns the best reduced costs (w.r.t. root reduced cost propagation) of the variable in the root node's relaxation,
13184  * if the root relaxation is not yet completely solved, or the variable was no column of the root LP, SCIP_INVALID is
13185  * returned
13186  */
13188  SCIP_VAR* var /**< problem variable */
13189  )
13190 {
13191  assert(var != NULL);
13192 
13193  switch( SCIPvarGetStatus(var) )
13194  {
13196  if( var->data.original.transvar == NULL )
13197  return SCIP_INVALID;
13199 
13200  case SCIP_VARSTATUS_LOOSE:
13201  case SCIP_VARSTATUS_COLUMN:
13202  return var->bestrootredcost;
13203 
13204  case SCIP_VARSTATUS_FIXED:
13208  return 0.0;
13209 
13210  default:
13211  SCIPerrorMessage("unknown variable status\n");
13212  SCIPABORT();
13213  return 0.0; /*lint !e527*/
13214  }
13215 }
13216 
13217 /** returns the best objective value (w.r.t. root reduced cost propagation) of the root LP which belongs the root
13218  * reduced cost which is accessible via SCIPvarGetRootRedcost() or the variable was no column of the root LP,
13219  * SCIP_INVALID is returned
13220  */
13222  SCIP_VAR* var /**< problem variable */
13223  )
13224 {
13225  assert(var != NULL);
13226 
13227  switch( SCIPvarGetStatus(var) )
13228  {
13230  if( var->data.original.transvar == NULL )
13231  return SCIP_INVALID;
13233 
13234  case SCIP_VARSTATUS_LOOSE:
13235  case SCIP_VARSTATUS_COLUMN:
13236  return var->bestrootlpobjval;
13237 
13238  case SCIP_VARSTATUS_FIXED:
13242  return SCIP_INVALID;
13243 
13244  default:
13245  SCIPerrorMessage("unknown variable status\n");
13246  SCIPABORT();
13247  return SCIP_INVALID; /*lint !e527*/
13248  }
13249 }
13250 
13251 /** set the given solution as the best root solution w.r.t. root reduced cost propagation in the variables */
13253  SCIP_VAR* var, /**< problem variable */
13254  SCIP_Real rootsol, /**< root solution value */
13255  SCIP_Real rootredcost, /**< root reduced cost */
13256  SCIP_Real rootlpobjval /**< objective value of the root LP */
13257  )
13258 {
13259  assert(var != NULL);
13260 
13261  var->bestrootsol = rootsol;
13262  var->bestrootredcost = rootredcost;
13263  var->bestrootlpobjval = rootlpobjval;
13264 }
13265 
13266 /** stores the solution value as relaxation solution in the problem variable */
13268  SCIP_VAR* var, /**< problem variable */
13269  SCIP_SET* set, /**< global SCIP settings */
13270  SCIP_RELAXATION* relaxation, /**< global relaxation data */
13271  SCIP_Real solval, /**< solution value in the current relaxation solution */
13272  SCIP_Bool updateobj /**< should the objective value be updated? */
13273  )
13274 {
13275  assert(var != NULL);
13276  assert(relaxation != NULL);
13277  assert(set != NULL);
13278  assert(var->scip == set->scip);
13279 
13280  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13281  switch( SCIPvarGetStatus(var) )
13282  {
13284  SCIP_CALL( SCIPvarSetRelaxSol(var->data.original.transvar, set, relaxation, solval, updateobj) );
13285  break;
13286 
13287  case SCIP_VARSTATUS_LOOSE:
13288  case SCIP_VARSTATUS_COLUMN:
13289  if( updateobj )
13290  SCIPrelaxationSolObjAdd(relaxation, var->obj * (solval - var->relaxsol));
13291  var->relaxsol = solval;
13292  break;
13293 
13294  case SCIP_VARSTATUS_FIXED:
13295  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13296  {
13297  SCIPerrorMessage("cannot set relaxation solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13298  SCIPvarGetName(var), var->glbdom.lb, solval);
13299  return SCIP_INVALIDDATA;
13300  }
13301  break;
13302 
13303  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13304  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13305  SCIP_CALL( SCIPvarSetRelaxSol(var->data.aggregate.var, set, relaxation,
13306  (solval - var->data.aggregate.constant)/var->data.aggregate.scalar, updateobj) );
13307  break;
13309  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13310  return SCIP_INVALIDDATA;
13311 
13313  SCIP_CALL( SCIPvarSetRelaxSol(var->negatedvar, set, relaxation, var->data.negate.constant - solval, updateobj) );
13314  break;
13315 
13316  default:
13317  SCIPerrorMessage("unknown variable status\n");
13318  return SCIP_INVALIDDATA;
13319  }
13320 
13321  return SCIP_OKAY;
13322 }
13323 
13324 /** returns the solution value of the problem variable in the relaxation solution
13325  *
13326  * @todo Inline this function - similar to SCIPvarGetLPSol_rec.
13327  */
13329  SCIP_VAR* var, /**< problem variable */
13330  SCIP_SET* set /**< global SCIP settings */
13331  )
13332 {
13333  SCIP_Real solvalsum;
13334  SCIP_Real solval;
13335  int i;
13336 
13337  assert(var != NULL);
13338  assert(set != NULL);
13339  assert(var->scip == set->scip);
13340 
13341  /* only values for non fixed variables (LOOSE or COLUMN) are stored; others have to be transformed */
13342  switch( SCIPvarGetStatus(var) )
13343  {
13345  return SCIPvarGetRelaxSol(var->data.original.transvar, set);
13346 
13347  case SCIP_VARSTATUS_LOOSE:
13348  case SCIP_VARSTATUS_COLUMN:
13349  return var->relaxsol;
13350 
13351  case SCIP_VARSTATUS_FIXED:
13352  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetUbGlobal(var)); /*lint !e777*/
13353  assert(SCIPvarGetLbLocal(var) == SCIPvarGetUbLocal(var)); /*lint !e777*/
13354  assert(SCIPvarGetLbGlobal(var) == SCIPvarGetLbLocal(var)); /*lint !e777*/
13355  return SCIPvarGetLbGlobal(var);
13356 
13357  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13358  solval = SCIPvarGetRelaxSol(var->data.aggregate.var, set);
13359  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13360  {
13361  if( var->data.aggregate.scalar * solval > 0.0 )
13362  return SCIPsetInfinity(set);
13363  if( var->data.aggregate.scalar * solval < 0.0 )
13364  return -SCIPsetInfinity(set);
13365  }
13366  return var->data.aggregate.scalar * solval + var->data.aggregate.constant;
13367 
13369  solvalsum = var->data.multaggr.constant;
13370  for( i = 0; i < var->data.multaggr.nvars; ++i )
13371  {
13372  solval = SCIPvarGetRelaxSol(var->data.multaggr.vars[i], set);
13373  if( SCIPsetIsInfinity(set, solval) || SCIPsetIsInfinity(set, -solval) )
13374  {
13375  if( var->data.multaggr.scalars[i] * solval > 0.0 )
13376  return SCIPsetInfinity(set);
13377  if( var->data.multaggr.scalars[i] * solval < 0.0 )
13378  return -SCIPsetInfinity(set);
13379  }
13380  solvalsum += var->data.multaggr.scalars[i] * solval;
13381  }
13382  return solvalsum;
13383 
13385  solval = SCIPvarGetRelaxSol(var->negatedvar, set);
13386  if( SCIPsetIsInfinity(set, solval) )
13387  return -SCIPsetInfinity(set);
13388  if( SCIPsetIsInfinity(set, -solval) )
13389  return SCIPsetInfinity(set);
13390  return var->data.negate.constant - solval;
13391 
13392  default:
13393  SCIPerrorMessage("unknown variable status\n");
13394  SCIPABORT();
13395  return SCIP_INVALID; /*lint !e527*/
13396  }
13397 }
13398 
13399 /** returns the solution value of the transformed problem variable in the relaxation solution */
13401  SCIP_VAR* var /**< problem variable */
13402  )
13403 {
13404  assert(var != NULL);
13406 
13407  return var->relaxsol;
13408 }
13409 
13410 /** stores the solution value as NLP solution in the problem variable */
13412  SCIP_VAR* var, /**< problem variable */
13413  SCIP_SET* set, /**< global SCIP settings */
13414  SCIP_Real solval /**< solution value in the current NLP solution */
13415  )
13416 {
13417  assert(var != NULL);
13418  assert(set != NULL);
13419  assert(var->scip == set->scip);
13420 
13421  /* we want to store only values for non fixed variables (LOOSE or COLUMN); others have to be transformed */
13422  switch( SCIPvarGetStatus(var) )
13423  {
13425  SCIP_CALL( SCIPvarSetNLPSol(var->data.original.transvar, set, solval) );
13426  break;
13427 
13428  case SCIP_VARSTATUS_LOOSE:
13429  case SCIP_VARSTATUS_COLUMN:
13430  var->nlpsol = solval;
13431  break;
13432 
13433  case SCIP_VARSTATUS_FIXED:
13434  if( !SCIPsetIsEQ(set, solval, var->glbdom.lb) )
13435  {
13436  SCIPerrorMessage("cannot set NLP solution value for variable <%s> fixed to %.15g to different value %.15g\n",
13437  SCIPvarGetName(var), var->glbdom.lb, solval);
13438  SCIPABORT();
13439  return SCIP_INVALIDCALL; /*lint !e527*/
13440  }
13441  break;
13442 
13443  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c => y = (x-c)/a */
13444  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13445  SCIP_CALL( SCIPvarSetNLPSol(var->data.aggregate.var, set, (solval - var->data.aggregate.constant)/var->data.aggregate.scalar) );
13446  break;
13447 
13449  SCIPerrorMessage("cannot set solution value for multiple aggregated variable\n");
13450  SCIPABORT();
13451  return SCIP_INVALIDCALL; /*lint !e527*/
13452 
13454  SCIP_CALL( SCIPvarSetNLPSol(var->negatedvar, set, var->data.negate.constant - solval) );
13455  break;
13456 
13457  default:
13458  SCIPerrorMessage("unknown variable status\n");
13459  SCIPABORT();
13460  return SCIP_ERROR; /*lint !e527*/
13461  }
13462 
13463  return SCIP_OKAY;
13464 }
13465 
13466 /** returns a weighted average solution value of the variable in all feasible primal solutions found so far */
13468  SCIP_VAR* var /**< problem variable */
13469  )
13470 {
13471  SCIP_Real avgsol;
13472  int i;
13473 
13474  assert(var != NULL);
13475 
13476  switch( SCIPvarGetStatus(var) )
13477  {
13479  if( var->data.original.transvar == NULL )
13480  return 0.0;
13481  return SCIPvarGetAvgSol(var->data.original.transvar);
13482 
13483  case SCIP_VARSTATUS_LOOSE:
13484  case SCIP_VARSTATUS_COLUMN:
13485  avgsol = var->primsolavg;
13486  avgsol = MAX(avgsol, var->glbdom.lb);
13487  avgsol = MIN(avgsol, var->glbdom.ub);
13488  return avgsol;
13489 
13490  case SCIP_VARSTATUS_FIXED:
13491  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13492  return var->locdom.lb;
13493 
13495  assert(var->data.aggregate.var != NULL);
13496  return var->data.aggregate.scalar * SCIPvarGetAvgSol(var->data.aggregate.var)
13497  + var->data.aggregate.constant;
13498 
13500  assert(!var->donotmultaggr);
13501  assert(var->data.multaggr.vars != NULL);
13502  assert(var->data.multaggr.scalars != NULL);
13503  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13504  * assert(var->data.multaggr.nvars >= 2);
13505  */
13506  avgsol = var->data.multaggr.constant;
13507  for( i = 0; i < var->data.multaggr.nvars; ++i )
13508  avgsol += var->data.multaggr.scalars[i] * SCIPvarGetAvgSol(var->data.multaggr.vars[i]);
13509  return avgsol;
13510 
13511  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13512  assert(var->negatedvar != NULL);
13514  assert(var->negatedvar->negatedvar == var);
13515  return var->data.negate.constant - SCIPvarGetAvgSol(var->negatedvar);
13516 
13517  default:
13518  SCIPerrorMessage("unknown variable status\n");
13519  SCIPABORT();
13520  return 0.0; /*lint !e527*/
13521  }
13522 }
13523 
13524 /** returns solution value and index of variable lower bound that is closest to the variable's value in the given primal solution
13525  * or current LP solution if no primal solution is given; returns an index of -1 if no variable lower bound is available
13526  */
13528  SCIP_VAR* var, /**< active problem variable */
13529  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13530  SCIP_SET* set, /**< global SCIP settings */
13531  SCIP_STAT* stat, /**< problem statistics */
13532  SCIP_Real* closestvlb, /**< pointer to store the value of the closest variable lower bound */
13533  int* closestvlbidx /**< pointer to store the index of the closest variable lower bound */
13534  )
13535 {
13536  int nvlbs;
13537 
13538  assert(var != NULL);
13539  assert(stat != NULL);
13540  assert(set != NULL);
13541  assert(var->scip == set->scip);
13542  assert(closestvlb != NULL);
13543  assert(closestvlbidx != NULL);
13544 
13545  *closestvlbidx = -1;
13546  *closestvlb = SCIP_REAL_MIN;
13547 
13548  nvlbs = SCIPvarGetNVlbs(var);
13549  if( nvlbs > 0 )
13550  {
13551  SCIP_VAR** vlbvars;
13552  SCIP_Real* vlbcoefs;
13553  SCIP_Real* vlbconsts;
13554  int i;
13555 
13556  vlbvars = SCIPvarGetVlbVars(var);
13557  vlbcoefs = SCIPvarGetVlbCoefs(var);
13558  vlbconsts = SCIPvarGetVlbConstants(var);
13559 
13560  /* check for cached values */
13561  if( var->closestvblpcount == stat->lpcount && var->closestvlbidx != -1 && sol == NULL)
13562  {
13563  i = var->closestvlbidx;
13564  assert(0 <= i && i < nvlbs);
13565  assert(SCIPvarIsActive(vlbvars[i]));
13566  *closestvlbidx = i;
13567  *closestvlb = vlbcoefs[i] * SCIPvarGetLPSol(vlbvars[i]) + vlbconsts[i];
13568  }
13569  else
13570  {
13571  /* search best VUB */
13572  for( i = 0; i < nvlbs; i++ )
13573  {
13574  if( SCIPvarIsActive(vlbvars[i]) )
13575  {
13576  SCIP_Real vlbsol;
13577 
13578  vlbsol = vlbcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vlbvars[i]) : SCIPsolGetVal(sol, set, stat, vlbvars[i])) + vlbconsts[i];
13579  if( vlbsol > *closestvlb )
13580  {
13581  *closestvlb = vlbsol;
13582  *closestvlbidx = i;
13583  }
13584  }
13585  }
13586 
13587  if( sol == NULL )
13588  {
13589  /* update cached value */
13590  if( var->closestvblpcount != stat->lpcount )
13591  var->closestvubidx = -1;
13592  var->closestvlbidx = *closestvlbidx;
13593  var->closestvblpcount = stat->lpcount;
13594  }
13595  }
13596  }
13597 }
13598 
13599 /** returns solution value and index of variable upper bound that is closest to the variable's value in the given primal solution;
13600  * or current LP solution if no primal solution is given; returns an index of -1 if no variable upper bound is available
13601  */
13603  SCIP_VAR* var, /**< active problem variable */
13604  SCIP_SOL* sol, /**< primal solution, or NULL for LP solution */
13605  SCIP_SET* set, /**< global SCIP settings */
13606  SCIP_STAT* stat, /**< problem statistics */
13607  SCIP_Real* closestvub, /**< pointer to store the value of the closest variable upper bound */
13608  int* closestvubidx /**< pointer to store the index of the closest variable upper bound */
13609  )
13610 {
13611  int nvubs;
13612 
13613  assert(var != NULL);
13614  assert(set != NULL);
13615  assert(var->scip == set->scip);
13616  assert(closestvub != NULL);
13617  assert(closestvubidx != NULL);
13618 
13619  *closestvubidx = -1;
13620  *closestvub = SCIP_REAL_MAX;
13621 
13622  nvubs = SCIPvarGetNVubs(var);
13623  if( nvubs > 0 )
13624  {
13625  SCIP_VAR** vubvars;
13626  SCIP_Real* vubcoefs;
13627  SCIP_Real* vubconsts;
13628  int i;
13629 
13630  vubvars = SCIPvarGetVubVars(var);
13631  vubcoefs = SCIPvarGetVubCoefs(var);
13632  vubconsts = SCIPvarGetVubConstants(var);
13633 
13634  /* check for cached values */
13635  if( var->closestvblpcount == stat->lpcount && var->closestvubidx != -1 && sol == NULL)
13636  {
13637  i = var->closestvubidx;
13638  assert(0 <= i && i < nvubs);
13639  assert(SCIPvarIsActive(vubvars[i]));
13640  *closestvubidx = i;
13641  *closestvub = vubcoefs[i] * SCIPvarGetLPSol(vubvars[i]) + vubconsts[i];
13642  }
13643  else
13644  {
13645  /* search best VUB */
13646  for( i = 0; i < nvubs; i++ )
13647  {
13648  if( SCIPvarIsActive(vubvars[i]) )
13649  {
13650  SCIP_Real vubsol;
13651 
13652  vubsol = vubcoefs[i] * (sol == NULL ? SCIPvarGetLPSol(vubvars[i]) : SCIPsolGetVal(sol, set, stat, vubvars[i])) + vubconsts[i];
13653  if( vubsol < *closestvub )
13654  {
13655  *closestvub = vubsol;
13656  *closestvubidx = i;
13657  }
13658  }
13659  }
13660 
13661  if( sol == NULL )
13662  {
13663  /* update cached value */
13664  if( var->closestvblpcount != stat->lpcount )
13665  var->closestvlbidx = -1;
13666  var->closestvubidx = *closestvubidx;
13667  var->closestvblpcount = stat->lpcount;
13668  }
13669  }
13670  }
13671 }
13672 
13673 /** resolves variable to columns and adds them with the coefficient to the row */
13675  SCIP_VAR* var, /**< problem variable */
13676  BMS_BLKMEM* blkmem, /**< block memory */
13677  SCIP_SET* set, /**< global SCIP settings */
13678  SCIP_STAT* stat, /**< problem statistics */
13679  SCIP_EVENTQUEUE* eventqueue, /**< event queue */
13680  SCIP_PROB* prob, /**< problem data */
13681  SCIP_LP* lp, /**< current LP data */
13682  SCIP_ROW* row, /**< LP row */
13683  SCIP_Real val /**< value of coefficient */
13684  )
13685 {
13686  int i;
13687 
13688  assert(var != NULL);
13689  assert(set != NULL);
13690  assert(var->scip == set->scip);
13691  assert(row != NULL);
13692  assert(!SCIPsetIsInfinity(set, REALABS(val)));
13693 
13694  SCIPsetDebugMsg(set, "adding coefficient %g<%s> to row <%s>\n", val, var->name, row->name);
13695 
13696  if ( SCIPsetIsZero(set, val) )
13697  return SCIP_OKAY;
13698 
13699  switch( SCIPvarGetStatus(var) )
13700  {
13702  if( var->data.original.transvar == NULL )
13703  {
13704  SCIPerrorMessage("cannot add untransformed original variable <%s> to LP row <%s>\n", var->name, row->name);
13705  return SCIP_INVALIDDATA;
13706  }
13707  SCIP_CALL( SCIPvarAddToRow(var->data.original.transvar, blkmem, set, stat, eventqueue, prob, lp, row, val) );
13708  return SCIP_OKAY;
13709 
13710  case SCIP_VARSTATUS_LOOSE:
13711  /* add globally fixed variables as constant */
13712  if( SCIPsetIsEQ(set, var->glbdom.lb, var->glbdom.ub) )
13713  {
13714  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->glbdom.lb) );
13715  return SCIP_OKAY;
13716  }
13717  /* convert loose variable into column */
13718  SCIP_CALL( SCIPvarColumn(var, blkmem, set, stat, prob, lp) );
13719  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
13720  /*lint -fallthrough*/
13721 
13722  case SCIP_VARSTATUS_COLUMN:
13723  assert(var->data.col != NULL);
13724  assert(var->data.col->var == var);
13725  SCIP_CALL( SCIProwIncCoef(row, blkmem, set, eventqueue, lp, var->data.col, val) );
13726  return SCIP_OKAY;
13727 
13728  case SCIP_VARSTATUS_FIXED:
13729  assert(var->glbdom.lb == var->glbdom.ub); /*lint !e777*/
13730  assert(var->locdom.lb == var->locdom.ub); /*lint !e777*/
13731  assert(var->locdom.lb == var->glbdom.lb); /*lint !e777*/
13732  assert(!SCIPsetIsInfinity(set, REALABS(var->locdom.lb)));
13733  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, val * var->locdom.lb) );
13734  return SCIP_OKAY;
13735 
13737  assert(var->data.aggregate.var != NULL);
13738  SCIP_CALL( SCIPvarAddToRow(var->data.aggregate.var, blkmem, set, stat, eventqueue, prob, lp,
13739  row, var->data.aggregate.scalar * val) );
13740  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.aggregate.constant * val) );
13741  return SCIP_OKAY;
13742 
13744  assert(!var->donotmultaggr);
13745  assert(var->data.multaggr.vars != NULL);
13746  assert(var->data.multaggr.scalars != NULL);
13747  /* Due to method SCIPvarFlattenAggregationGraph(), this assert is no longer correct
13748  * assert(var->data.multaggr.nvars >= 2);
13749  */
13750  for( i = 0; i < var->data.multaggr.nvars; ++i )
13751  {
13752  SCIP_CALL( SCIPvarAddToRow(var->data.multaggr.vars[i], blkmem, set, stat, eventqueue, prob, lp,
13753  row, var->data.multaggr.scalars[i] * val) );
13754  }
13755  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.multaggr.constant * val) );
13756  return SCIP_OKAY;
13757 
13758  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
13759  assert(var->negatedvar != NULL);
13761  assert(var->negatedvar->negatedvar == var);
13762  SCIP_CALL( SCIPvarAddToRow(var->negatedvar, blkmem, set, stat, eventqueue, prob, lp, row, -val) );
13763  SCIP_CALL( SCIProwAddConstant(row, blkmem, set, stat, eventqueue, lp, var->data.negate.constant * val) );
13764  return SCIP_OKAY;
13765 
13766  default:
13767  SCIPerrorMessage("unknown variable status\n");
13768  return SCIP_INVALIDDATA;
13769  }
13770 }
13771 
13772 /* optionally, define this compiler flag to write complete variable histories to a file */
13773 #ifdef SCIP_HISTORYTOFILE
13774 SCIP_Longint counter = 0l;
13775 const char* historypath="."; /* allows for user-defined path; use '.' for calling directory of SCIP */
13776 #include "scip/scip.h"
13777 #endif
13778 
13779 /** updates the pseudo costs of the given variable and the global pseudo costs after a change of
13780  * "solvaldelta" in the variable's solution value and resulting change of "objdelta" in the in the LP's objective value
13781  */
13783  SCIP_VAR* var, /**< problem variable */
13784  SCIP_SET* set, /**< global SCIP settings */
13785  SCIP_STAT* stat, /**< problem statistics */
13786  SCIP_Real solvaldelta, /**< difference of variable's new LP value - old LP value */
13787  SCIP_Real objdelta, /**< difference of new LP's objective value - old LP's objective value */
13788  SCIP_Real weight /**< weight in (0,1] of this update in pseudo cost sum */
13789  )
13790 {
13791  SCIP_Real oldrootpseudocosts;
13792  assert(var != NULL);
13793  assert(set != NULL);
13794  assert(var->scip == set->scip);
13795  assert(stat != NULL);
13796 
13797  /* check if history statistics should be collected for a variable */
13798  if( !stat->collectvarhistory )
13799  return SCIP_OKAY;
13800 
13801  switch( SCIPvarGetStatus(var) )
13802  {
13804  if( var->data.original.transvar == NULL )
13805  {
13806  SCIPerrorMessage("cannot update pseudo costs of original untransformed variable\n");
13807  return SCIP_INVALIDDATA;
13808  }
13809  SCIP_CALL( SCIPvarUpdatePseudocost(var->data.original.transvar, set, stat, solvaldelta, objdelta, weight) );
13810  return SCIP_OKAY;
13811 
13812  case SCIP_VARSTATUS_LOOSE:
13813  case SCIP_VARSTATUS_COLUMN:
13814  /* store old pseudo-costs for root LP best-estimate update */
13815  oldrootpseudocosts = SCIPvarGetMinPseudocostScore(var, stat, set, SCIPvarGetRootSol(var));
13816 
13817  /* update history */
13818  SCIPhistoryUpdatePseudocost(var->history, set, solvaldelta, objdelta, weight);
13819  SCIPhistoryUpdatePseudocost(var->historycrun, set, solvaldelta, objdelta, weight);
13820  SCIPhistoryUpdatePseudocost(stat->glbhistory, set, solvaldelta, objdelta, weight);
13821  SCIPhistoryUpdatePseudocost(stat->glbhistorycrun, set, solvaldelta, objdelta, weight);
13822 
13823  /* update root LP best-estimate */
13824  SCIP_CALL( SCIPstatUpdateVarRootLPBestEstimate(stat, set, var, oldrootpseudocosts) );
13825 
13826  /* append history to file */
13827 #ifdef SCIP_HISTORYTOFILE
13828  {
13829  FILE* f;
13830  char filename[256];
13831  SCIP_NODE* currentnode;
13832  SCIP_NODE* parentnode;
13833  currentnode = SCIPgetFocusNode(set->scip);
13834  parentnode = SCIPnodeGetParent(currentnode);
13835 
13836  sprintf(filename, "%s/%s.pse", historypath, SCIPgetProbName(set->scip));
13837  f = fopen(filename, "a");
13838  if( NULL != f )
13839  {
13840  fprintf(f, "%lld %s \t %lld \t %lld \t %lld \t %d \t %15.9f \t %.3f\n",
13841  ++counter,
13842  SCIPvarGetName(var),
13843  SCIPnodeGetNumber(currentnode),
13844  parentnode != NULL ? SCIPnodeGetNumber(parentnode) : -1,
13845  SCIPgetNLPIterations(set->scip),
13846  SCIPgetDepth(set->scip),
13847  objdelta,
13848  solvaldelta);
13849  fclose(f);
13850  }
13851  }
13852 #endif
13853  return SCIP_OKAY;
13854 
13855  case SCIP_VARSTATUS_FIXED:
13856  SCIPerrorMessage("cannot update pseudo cost values of a fixed variable\n");
13857  return SCIP_INVALIDDATA;
13858 
13860  assert(!SCIPsetIsZero(set, var->data.aggregate.scalar));
13862  solvaldelta/var->data.aggregate.scalar, objdelta, weight) );
13863  return SCIP_OKAY;
13864 
13866  SCIPerrorMessage("cannot update pseudo cost values of a multi-aggregated variable\n");
13867  return SCIP_INVALIDDATA;
13868 
13870  SCIP_CALL( SCIPvarUpdatePseudocost(var->negatedvar, set, stat, -solvaldelta, objdelta, weight) );
13871  return SCIP_OKAY;
13872 
13873  default:
13874  SCIPerrorMessage("unknown variable status\n");
13875  return SCIP_INVALIDDATA;
13876  }
13877 }
13878 
13879 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value */
13881  SCIP_VAR* var, /**< problem variable */
13882  SCIP_STAT* stat, /**< problem statistics */
13883  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13884  )
13885 {
13886  SCIP_BRANCHDIR dir;
13887 
13888  assert(var != NULL);
13889  assert(stat != NULL);
13890 
13891  switch( SCIPvarGetStatus(var) )
13892  {
13894  if( var->data.original.transvar == NULL )
13895  return SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13896  else
13897  return SCIPvarGetPseudocost(var->data.original.transvar, stat, solvaldelta);
13898 
13899  case SCIP_VARSTATUS_LOOSE:
13900  case SCIP_VARSTATUS_COLUMN:
13901  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13902 
13903  return SCIPhistoryGetPseudocostCount(var->history, dir) > 0.0
13904  ? SCIPhistoryGetPseudocost(var->history, solvaldelta)
13905  : SCIPhistoryGetPseudocost(stat->glbhistory, solvaldelta);
13906 
13907  case SCIP_VARSTATUS_FIXED:
13908  return 0.0;
13909 
13911  return SCIPvarGetPseudocost(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13912 
13914  return 0.0;
13915 
13917  return SCIPvarGetPseudocost(var->negatedvar, stat, -solvaldelta);
13918 
13919  default:
13920  SCIPerrorMessage("unknown variable status\n");
13921  SCIPABORT();
13922  return 0.0; /*lint !e527*/
13923  }
13924 }
13925 
13926 /** gets the variable's pseudo cost value for the given step size "solvaldelta" in the variable's LP solution value,
13927  * only using the pseudo cost information of the current run
13928  */
13930  SCIP_VAR* var, /**< problem variable */
13931  SCIP_STAT* stat, /**< problem statistics */
13932  SCIP_Real solvaldelta /**< difference of variable's new LP value - old LP value */
13933  )
13934 {
13935  SCIP_BRANCHDIR dir;
13936 
13937  assert(var != NULL);
13938  assert(stat != NULL);
13939 
13940  switch( SCIPvarGetStatus(var) )
13941  {
13943  if( var->data.original.transvar == NULL )
13944  return SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13945  else
13946  return SCIPvarGetPseudocostCurrentRun(var->data.original.transvar, stat, solvaldelta);
13947 
13948  case SCIP_VARSTATUS_LOOSE:
13949  case SCIP_VARSTATUS_COLUMN:
13950  dir = (solvaldelta >= 0.0 ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
13951 
13952  return SCIPhistoryGetPseudocostCount(var->historycrun, dir) > 0.0
13953  ? SCIPhistoryGetPseudocost(var->historycrun, solvaldelta)
13954  : SCIPhistoryGetPseudocost(stat->glbhistorycrun, solvaldelta);
13955 
13956  case SCIP_VARSTATUS_FIXED:
13957  return 0.0;
13958 
13960  return SCIPvarGetPseudocostCurrentRun(var->data.aggregate.var, stat, var->data.aggregate.scalar * solvaldelta);
13961 
13963  return 0.0;
13964 
13966  return SCIPvarGetPseudocostCurrentRun(var->negatedvar, stat, -solvaldelta);
13967 
13968  default:
13969  SCIPerrorMessage("unknown variable status\n");
13970  SCIPABORT();
13971  return 0.0; /*lint !e527*/
13972  }
13973 }
13974 
13975 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction */
13977  SCIP_VAR* var, /**< problem variable */
13978  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
13979  )
13980 {
13981  assert(var != NULL);
13982  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
13983 
13984  switch( SCIPvarGetStatus(var) )
13985  {
13987  if( var->data.original.transvar == NULL )
13988  return 0.0;
13989  else
13990  return SCIPvarGetPseudocostCount(var->data.original.transvar, dir);
13991 
13992  case SCIP_VARSTATUS_LOOSE:
13993  case SCIP_VARSTATUS_COLUMN:
13994  return SCIPhistoryGetPseudocostCount(var->history, dir);
13995 
13996  case SCIP_VARSTATUS_FIXED:
13997  return 0.0;
13998 
14000  if( var->data.aggregate.scalar > 0.0 )
14001  return SCIPvarGetPseudocostCount(var->data.aggregate.var, dir);
14002  else
14004 
14006  return 0.0;
14007 
14010 
14011  default:
14012  SCIPerrorMessage("unknown variable status\n");
14013  SCIPABORT();
14014  return 0.0; /*lint !e527*/
14015  }
14016 }
14017 
14018 /** gets the variable's (possible fractional) number of pseudo cost updates for the given direction,
14019  * only using the pseudo cost information of the current run
14020  */
14022  SCIP_VAR* var, /**< problem variable */
14023  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14024  )
14025 {
14026  assert(var != NULL);
14027  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14028 
14029  switch( SCIPvarGetStatus(var) )
14030  {
14032  if( var->data.original.transvar == NULL )
14033  return 0.0;
14034  else
14036 
14037  case SCIP_VARSTATUS_LOOSE:
14038  case SCIP_VARSTATUS_COLUMN:
14039  return SCIPhistoryGetPseudocostCount(var->historycrun, dir);
14040 
14041  case SCIP_VARSTATUS_FIXED:
14042  return 0.0;
14043 
14045  if( var->data.aggregate.scalar > 0.0 )
14047  else
14049 
14051  return 0.0;
14052 
14055 
14056  default:
14057  SCIPerrorMessage("unknown variable status\n");
14058  SCIPABORT();
14059  return 0.0; /*lint !e527*/
14060  }
14061 }
14062 
14063 /** compares both possible directions for rounding the given solution value and returns the minimum pseudo-costs of the variable */
14065  SCIP_VAR* var, /**< problem variable */
14066  SCIP_STAT* stat, /**< problem statistics */
14067  SCIP_SET* set, /**< global SCIP settings */
14068  SCIP_Real solval /**< solution value, e.g., LP solution value */
14069  )
14070 {
14071  SCIP_Real upscore;
14072  SCIP_Real downscore;
14073  SCIP_Real solvaldeltaup;
14074  SCIP_Real solvaldeltadown;
14075 
14076  /* LP root estimate only works for variables with fractional LP root solution */
14077  if( SCIPsetIsFeasIntegral(set, solval) )
14078  return 0.0;
14079 
14080  /* no min pseudo-cost score is calculated as long as the variable was not initialized in a direction */
14082  return 0.0;
14083 
14084  /* compute delta's to ceil and floor of root LP solution value */
14085  solvaldeltaup = SCIPsetCeil(set, solval) - solval;
14086  solvaldeltadown = SCIPsetFloor(set, solval) - solval;
14087 
14088 
14089  upscore = SCIPvarGetPseudocost(var, stat, solvaldeltaup);
14090  downscore = SCIPvarGetPseudocost(var, stat, solvaldeltadown);
14091 
14092  return MIN(upscore, downscore);
14093 }
14094 
14095 /** gets the an estimate of the variable's pseudo cost variance in direction \p dir */
14097  SCIP_VAR* var, /**< problem variable */
14098  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14099  SCIP_Bool onlycurrentrun /**< return pseudo cost variance only for current branch and bound run */
14100  )
14101 {
14102  assert(var != NULL);
14103  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14104 
14105  switch( SCIPvarGetStatus(var) )
14106  {
14108  if( var->data.original.transvar == NULL )
14109  return 0.0;
14110  else
14111  return SCIPvarGetPseudocostVariance(var->data.original.transvar, dir, onlycurrentrun);
14112 
14113  case SCIP_VARSTATUS_LOOSE:
14114  case SCIP_VARSTATUS_COLUMN:
14115  if( onlycurrentrun )
14117  else
14118  return SCIPhistoryGetPseudocostVariance(var->history, dir);
14119 
14120  case SCIP_VARSTATUS_FIXED:
14121  return 0.0;
14122 
14124  if( var->data.aggregate.scalar > 0.0 )
14125  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, dir, onlycurrentrun);
14126  else
14127  return SCIPvarGetPseudocostVariance(var->data.aggregate.var, SCIPbranchdirOpposite(dir), onlycurrentrun);
14128 
14130  return 0.0;
14131 
14133  return SCIPvarGetPseudocostVariance(var->negatedvar, SCIPbranchdirOpposite(dir), onlycurrentrun);
14134 
14135  default:
14136  SCIPerrorMessage("unknown variable status\n");
14137  SCIPABORT();
14138  return 0.0; /*lint !e527*/
14139  }
14140 }
14141 
14142 /** calculates a confidence bound for this variable under the assumption of normally distributed pseudo costs
14143  *
14144  * The confidence bound \f$ \theta \geq 0\f$ denotes the interval borders \f$ [X - \theta, \ X + \theta]\f$, which contains
14145  * the true pseudo costs of the variable, i.e., the expected value of the normal distribution, with a probability
14146  * of 2 * clevel - 1.
14147  *
14148  * @return value of confidence bound for this variable
14149  */
14151  SCIP_VAR* var, /**< variable in question */
14152  SCIP_SET* set, /**< global SCIP settings */
14153  SCIP_BRANCHDIR dir, /**< the branching direction for the confidence bound */
14154  SCIP_Bool onlycurrentrun, /**< should only the current run be taken into account */
14155  SCIP_CONFIDENCELEVEL clevel /**< confidence level for the interval */
14156  )
14157 {
14158  SCIP_Real confidencebound;
14159 
14160  confidencebound = SCIPvarGetPseudocostVariance(var, dir, onlycurrentrun);
14161  if( SCIPsetIsFeasPositive(set, confidencebound) )
14162  {
14163  SCIP_Real count;
14164 
14165  if( onlycurrentrun )
14166  count = SCIPvarGetPseudocostCountCurrentRun(var, dir);
14167  else
14168  count = SCIPvarGetPseudocostCount(var, dir);
14169  /* assertion is valid because variance is positive */
14170  assert(count >= 1.9);
14171 
14172  confidencebound /= count; /*lint !e414 division by zero can obviously not occur */
14173  confidencebound = sqrt(confidencebound);
14174 
14175  /* the actual, underlying distribution of the mean is a student-t-distribution with degrees of freedom equal to
14176  * the number of pseudo cost evaluations of this variable in the respective direction. */
14177  confidencebound *= SCIPstudentTGetCriticalValue(clevel, (int)SCIPsetFloor(set, count) - 1);
14178  }
14179  else
14180  confidencebound = 0.0;
14181 
14182  return confidencebound;
14183 }
14184 
14185 /** check if the current pseudo cost relative error in a direction violates the given threshold. The Relative
14186  * Error is calculated at a specific confidence level
14187  */
14189  SCIP_VAR* var, /**< variable in question */
14190  SCIP_SET* set, /**< global SCIP settings */
14191  SCIP_STAT* stat, /**< problem statistics */
14192  SCIP_Real threshold, /**< threshold for relative errors to be considered reliable (enough) */
14193  SCIP_CONFIDENCELEVEL clevel /**< a given confidence level */
14194  )
14195 {
14196  SCIP_Real downsize;
14197  SCIP_Real upsize;
14198  SCIP_Real size;
14199  SCIP_Real relerrorup;
14200  SCIP_Real relerrordown;
14201  SCIP_Real relerror;
14202 
14203  /* check, if the pseudo cost score of the variable is reliable */
14206  size = MIN(downsize, upsize);
14207 
14208  /* Pseudo costs relative error can only be reliable if both directions have been tried at least twice */
14209  if( size <= 1.9 )
14210  return FALSE;
14211 
14212  /* use the relative error between the current mean pseudo cost value of the candidate and its upper
14213  * confidence interval bound at confidence level of 95% for individual variable reliability.
14214  * this is only possible if we have at least 2 measurements and therefore a valid variance estimate.
14215  */
14216  if( downsize >= 1.9 )
14217  {
14218  SCIP_Real normval;
14219 
14220  relerrordown = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_DOWNWARDS, TRUE, clevel);
14221  normval = SCIPvarGetPseudocostCurrentRun(var, stat, -1.0);
14222  normval = MAX(1.0, normval);
14223 
14224  relerrordown /= normval;
14225  }
14226  else
14227  relerrordown = 0.0;
14228 
14229  if( upsize >= 1.9 )
14230  {
14231  SCIP_Real normval;
14232 
14233  relerrorup = SCIPvarCalcPscostConfidenceBound(var, set, SCIP_BRANCHDIR_UPWARDS, TRUE, clevel);
14234  normval = SCIPvarGetPseudocostCurrentRun(var, stat, +1.0);
14235  normval = MAX(1.0, normval);
14236  relerrorup /= normval;
14237  }
14238  else
14239  relerrorup = 0.0;
14240 
14241  /* consider the relative error threshold violated, if it is violated in at least one branching direction */
14242  relerror = MAX(relerrorup, relerrordown);
14243 
14244  return (relerror <= threshold);
14245 }
14246 
14247 /** check if variable pseudo-costs have a significant difference in location. The significance depends on
14248  * the choice of \p clevel and on the kind of tested hypothesis. The one-sided hypothesis, which
14249  * should be rejected, is that fracy * mu_y >= fracx * mu_x, where mu_y and mu_x denote the
14250  * unknown location means of the underlying pseudo-cost distributions of x and y.
14251  *
14252  * This method is applied best if variable x has a better pseudo-cost score than y. The method hypothesizes that y were actually
14253  * better than x (despite the current information), meaning that y can be expected to yield branching
14254  * decisions as least as good as x in the long run. If the method returns TRUE, the current history information is
14255  * sufficient to safely rely on the alternative hypothesis that x yields indeed a better branching score (on average)
14256  * than y.
14257  *
14258  * @note The order of x and y matters for the one-sided hypothesis
14259  *
14260  * @note set \p onesided to FALSE if you are not sure which variable is better. The hypothesis tested then reads
14261  * fracy * mu_y == fracx * mu_x vs the alternative hypothesis fracy * mu_y != fracx * mu_x.
14262  *
14263  * @return TRUE if the hypothesis can be safely rejected at the given confidence level
14264  */
14266  SCIP_SET* set, /**< global SCIP settings */
14267  SCIP_STAT* stat, /**< problem statistics */
14268  SCIP_VAR* varx, /**< variable x */
14269  SCIP_Real fracx, /**< the fractionality of variable x */
14270  SCIP_VAR* vary, /**< variable y */
14271  SCIP_Real fracy, /**< the fractionality of variable y */
14272  SCIP_BRANCHDIR dir, /**< branching direction */
14273  SCIP_CONFIDENCELEVEL clevel, /**< confidence level for rejecting hypothesis */
14274  SCIP_Bool onesided /**< should a one-sided hypothesis y >= x be tested? */
14275  )
14276 {
14277  SCIP_Real meanx;
14278  SCIP_Real meany;
14279  SCIP_Real variancex;
14280  SCIP_Real variancey;
14281  SCIP_Real countx;
14282  SCIP_Real county;
14283  SCIP_Real tresult;
14284  SCIP_Real realdirection;
14285 
14286 
14287  if( varx == vary )
14288  return FALSE;
14289 
14290  countx = SCIPvarGetPseudocostCount(varx, dir);
14291  county = SCIPvarGetPseudocostCount(vary, dir);
14292 
14293  /* if not at least 2 measurements were taken, return FALSE */
14294  if( countx <= 1.9 || county <= 1.9 )
14295  return FALSE;
14296 
14297  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14298 
14299  meanx = fracx * SCIPvarGetPseudocost(varx, stat, realdirection);
14300  meany = fracy * SCIPvarGetPseudocost(vary, stat, realdirection);
14301 
14302  variancex = SQR(fracx) * SCIPvarGetPseudocostVariance(varx, dir, FALSE);
14303  variancey = SQR(fracy) * SCIPvarGetPseudocostVariance(vary, dir, FALSE);
14304 
14305  /* if there is no variance, the means are taken from a constant distribution */
14306  if( SCIPsetIsFeasEQ(set, variancex + variancey, 0.0) )
14307  return (onesided ? SCIPsetIsFeasGT(set, meanx, meany) : !SCIPsetIsFeasEQ(set, meanx, meany));
14308 
14309  tresult = SCIPcomputeTwoSampleTTestValue(meanx, meany, variancex, variancey, countx, county);
14310 
14311  /* for the two-sided hypothesis, just take the absolute of t */
14312  if( !onesided )
14313  tresult = REALABS(tresult);
14314 
14315  return (tresult >= SCIPstudentTGetCriticalValue(clevel, (int)(countx + county - 2)));
14316 }
14317 
14318 /** tests at a given confidence level whether the variable pseudo-costs only have a small probability to
14319  * exceed a \p threshold. This is useful to determine if past observations provide enough evidence
14320  * to skip an expensive strong-branching step if there is already a candidate that has been proven to yield an improvement
14321  * of at least \p threshold.
14322  *
14323  * @note use \p clevel to adjust the level of confidence. For SCIP_CONFIDENCELEVEL_MIN, the method returns TRUE if
14324  * the estimated probability to exceed \p threshold is less than 25 %.
14325  *
14326  * @see SCIP_Confidencelevel for a list of available levels. The used probability limits refer to the one-sided levels
14327  * of confidence.
14328  *
14329  * @return TRUE if the variable pseudo-cost probabilistic model is likely to be smaller than \p threshold
14330  * at the given confidence level \p clevel.
14331  */
14333  SCIP_SET* set, /**< global SCIP settings */
14334  SCIP_STAT* stat, /**< problem statistics */
14335  SCIP_VAR* var, /**< variable x */
14336  SCIP_Real frac, /**< the fractionality of variable x */
14337  SCIP_Real threshold, /**< the threshold to test against */
14338  SCIP_BRANCHDIR dir, /**< branching direction */
14339  SCIP_CONFIDENCELEVEL clevel /**< confidence level for rejecting hypothesis */
14340  )
14341 {
14342  SCIP_Real mean;
14343  SCIP_Real variance;
14344  SCIP_Real count;
14345  SCIP_Real realdirection;
14346  SCIP_Real probability;
14347  SCIP_Real problimit;
14348 
14349  count = SCIPvarGetPseudocostCount(var, dir);
14350 
14351  /* if not at least 2 measurements were taken, return FALSE */
14352  if( count <= 1.9 )
14353  return FALSE;
14354 
14355  realdirection = (dir == SCIP_BRANCHDIR_DOWNWARDS ? -1.0 : 1.0);
14356 
14357  mean = frac * SCIPvarGetPseudocost(var, stat, realdirection);
14358  variance = SQR(frac) * SCIPvarGetPseudocostVariance(var, dir, FALSE);
14359 
14360  /* if mean is at least threshold, it has at least a 50% probability to exceed threshold, we therefore return FALSE */
14361  if( SCIPsetIsFeasGE(set, mean, threshold) )
14362  return FALSE;
14363 
14364  /* if there is no variance, the means are taken from a constant distribution */
14365  if( SCIPsetIsFeasEQ(set, variance, 0.0) )
14366  return SCIPsetIsFeasLT(set, mean, threshold);
14367 
14368  /* obtain probability of a normally distributed random variable at given mean and variance to yield at most threshold */
14369  probability = SCIPnormalCDF(mean, variance, threshold);
14370 
14371  /* determine a probability limit corresponding to the given confidence level */
14372  switch( clevel )
14373  {
14375  problimit = 0.75;
14376  break;
14378  problimit = 0.875;
14379  break;
14381  problimit = 0.9;
14382  break;
14384  problimit = 0.95;
14385  break;
14387  problimit = 0.975;
14388  break;
14389  default:
14390  problimit = -1;
14391  SCIPerrorMessage("Confidence level set to unknown value <%d>", (int)clevel);
14392  SCIPABORT();
14393  break;
14394  }
14395 
14396  return (probability >= problimit);
14397 }
14398 
14399 /** find the corresponding history entry if already existing, otherwise create new entry */
14400 static
14402  SCIP_VAR* var, /**< problem variable */
14403  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14404  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14405  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14406  SCIP_HISTORY** history /**< pointer to store the value based history, or NULL */
14407  )
14408 {
14409  assert(var != NULL);
14410  assert(blkmem != NULL);
14411  assert(set != NULL);
14412  assert(history != NULL);
14413 
14414  (*history) = NULL;
14415 
14416  if( var->valuehistory == NULL )
14417  {
14418  SCIP_CALL( SCIPvaluehistoryCreate(&var->valuehistory, blkmem) );
14419  }
14420 
14421  SCIP_CALL( SCIPvaluehistoryFind(var->valuehistory, blkmem, set, value, history) );
14422 
14423  return SCIP_OKAY;
14424 }
14425 
14426 /** check if value based history should be used */
14427 static
14429  SCIP_VAR* var, /**< problem variable */
14430  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14431  SCIP_SET* set /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14432  )
14433 {
14434  /* check if the domain value is unknown (not specific) */
14435  if( value == SCIP_UNKNOWN ) /*lint !e777*/
14436  return FALSE;
14437 
14438  assert(set != NULL);
14439 
14440  /* check if value based history should be collected */
14441  if( !set->history_valuebased )
14442  return FALSE;
14443 
14444  /* value based history is not collected for binary variable since the standard history already contains all information */
14445  if( SCIPvarGetType(var) == SCIP_VARTYPE_BINARY )
14446  return FALSE;
14447 
14448  /* value based history is not collected for continuous variables */
14450  return FALSE;
14451 
14452  return TRUE;
14453 }
14454 
14455 /** increases VSIDS of the variable by the given weight */
14457  SCIP_VAR* var, /**< problem variable */
14458  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14459  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14460  SCIP_STAT* stat, /**< problem statistics */
14461  SCIP_BRANCHDIR dir, /**< branching direction */
14462  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14463  SCIP_Real weight /**< weight of this update in VSIDS */
14464  )
14465 {
14466  assert(var != NULL);
14467  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14468 
14469  /* check if history statistics should be collected for a variable */
14470  if( !stat->collectvarhistory )
14471  return SCIP_OKAY;
14472 
14473  if( SCIPsetIsZero(set, weight) )
14474  return SCIP_OKAY;
14475 
14476  switch( SCIPvarGetStatus(var) )
14477  {
14479  if( var->data.original.transvar == NULL )
14480  {
14481  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14482  return SCIP_INVALIDDATA;
14483  }
14484  SCIP_CALL( SCIPvarIncVSIDS(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14485  return SCIP_OKAY;
14486 
14487  case SCIP_VARSTATUS_LOOSE:
14488  case SCIP_VARSTATUS_COLUMN:
14489  {
14490  SCIPhistoryIncVSIDS(var->history, dir, weight);
14491  SCIPhistoryIncVSIDS(var->historycrun, dir, weight);
14492 
14493  if( useValuehistory(var, value, set) )
14494  {
14495  SCIP_HISTORY* history;
14496 
14497  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14498  assert(history != NULL);
14499 
14500  SCIPhistoryIncVSIDS(history, dir, weight);
14501  SCIPsetDebugMsg(set, "variable (<%s> %s %g) + <%g> = <%g>\n", SCIPvarGetName(var), dir == SCIP_BRANCHDIR_UPWARDS ? ">=" : "<=",
14502  value, weight, SCIPhistoryGetVSIDS(history, dir));
14503  }
14504 
14505  return SCIP_OKAY;
14506  }
14507  case SCIP_VARSTATUS_FIXED:
14508  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14509  return SCIP_INVALIDDATA;
14510 
14512  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14513 
14514  if( var->data.aggregate.scalar > 0.0 )
14515  {
14516  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14517  }
14518  else
14519  {
14520  assert(var->data.aggregate.scalar < 0.0);
14521  SCIP_CALL( SCIPvarIncVSIDS(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14522  }
14523  return SCIP_OKAY;
14524 
14526  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14527  return SCIP_INVALIDDATA;
14528 
14530  value = 1.0 - value;
14531 
14532  SCIP_CALL( SCIPvarIncVSIDS(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
14533  return SCIP_OKAY;
14534 
14535  default:
14536  SCIPerrorMessage("unknown variable status\n");
14537  return SCIP_INVALIDDATA;
14538  }
14539 }
14540 
14541 /** scales the VSIDS of the variable by the given scalar */
14543  SCIP_VAR* var, /**< problem variable */
14544  SCIP_Real scalar /**< scalar to multiply the VSIDSs with */
14545  )
14546 {
14547  assert(var != NULL);
14548 
14549  switch( SCIPvarGetStatus(var) )
14550  {
14552  if( var->data.original.transvar == NULL )
14553  {
14554  SCIPerrorMessage("cannot update VSIDS of original untransformed variable\n");
14555  return SCIP_INVALIDDATA;
14556  }
14558  return SCIP_OKAY;
14559 
14560  case SCIP_VARSTATUS_LOOSE:
14561  case SCIP_VARSTATUS_COLUMN:
14562  {
14563  SCIPhistoryScaleVSIDS(var->history, scalar);
14564  SCIPhistoryScaleVSIDS(var->historycrun, scalar);
14566 
14567  return SCIP_OKAY;
14568  }
14569  case SCIP_VARSTATUS_FIXED:
14570  SCIPerrorMessage("cannot update VSIDS of a fixed variable\n");
14571  return SCIP_INVALIDDATA;
14572 
14574  SCIP_CALL( SCIPvarScaleVSIDS(var->data.aggregate.var, scalar) );
14575  return SCIP_OKAY;
14576 
14578  SCIPerrorMessage("cannot update VSIDS of a multi-aggregated variable\n");
14579  return SCIP_INVALIDDATA;
14580 
14582  SCIP_CALL( SCIPvarScaleVSIDS(var->negatedvar, scalar) );
14583  return SCIP_OKAY;
14584 
14585  default:
14586  SCIPerrorMessage("unknown variable status\n");
14587  return SCIP_INVALIDDATA;
14588  }
14589 }
14590 
14591 /** increases the number of active conflicts by one and the overall length of the variable by the given length */
14593  SCIP_VAR* var, /**< problem variable */
14594  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14595  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14596  SCIP_STAT* stat, /**< problem statistics */
14597  SCIP_BRANCHDIR dir, /**< branching direction */
14598  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14599  SCIP_Real length /**< length of the conflict */
14600  )
14601 {
14602  assert(var != NULL);
14603  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14604 
14605  /* check if history statistics should be collected for a variable */
14606  if( !stat->collectvarhistory )
14607  return SCIP_OKAY;
14608 
14609  switch( SCIPvarGetStatus(var) )
14610  {
14612  if( var->data.original.transvar == NULL )
14613  {
14614  SCIPerrorMessage("cannot update conflict score of original untransformed variable\n");
14615  return SCIP_INVALIDDATA;
14616  }
14617  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.original.transvar, blkmem, set, stat, dir, value, length) );
14618  return SCIP_OKAY;
14619 
14620  case SCIP_VARSTATUS_LOOSE:
14621  case SCIP_VARSTATUS_COLUMN:
14622  {
14623  SCIPhistoryIncNActiveConflicts(var->history, dir, length);
14624  SCIPhistoryIncNActiveConflicts(var->historycrun, dir, length);
14625 
14626  if( useValuehistory(var, value, set) )
14627  {
14628  SCIP_HISTORY* history;
14629 
14630  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14631  assert(history != NULL);
14632 
14633  SCIPhistoryIncNActiveConflicts(history, dir, length);
14634  }
14635 
14636  return SCIP_OKAY;
14637  }
14638  case SCIP_VARSTATUS_FIXED:
14639  SCIPerrorMessage("cannot update conflict score of a fixed variable\n");
14640  return SCIP_INVALIDDATA;
14641 
14643  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14644 
14645  if( var->data.aggregate.scalar > 0.0 )
14646  {
14647  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, dir, value, length) );
14648  }
14649  else
14650  {
14651  assert(var->data.aggregate.scalar < 0.0);
14652  SCIP_CALL( SCIPvarIncNActiveConflicts(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14653  }
14654  return SCIP_OKAY;
14655 
14657  SCIPerrorMessage("cannot update conflict score of a multi-aggregated variable\n");
14658  return SCIP_INVALIDDATA;
14659 
14661  value = 1.0 - value;
14662 
14663  SCIP_CALL( SCIPvarIncNActiveConflicts(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, length) );
14664  return SCIP_OKAY;
14665 
14666  default:
14667  SCIPerrorMessage("unknown variable status\n");
14668  return SCIP_INVALIDDATA;
14669  }
14670 }
14671 
14672 /** gets the number of active conflicts containing this variable in given direction */
14674  SCIP_VAR* var, /**< problem variable */
14675  SCIP_STAT* stat, /**< problem statistics */
14676  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14677  )
14678 {
14679  assert(var != NULL);
14680  assert(stat != NULL);
14681  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14682 
14683  switch( SCIPvarGetStatus(var) )
14684  {
14686  if( var->data.original.transvar == NULL )
14687  return 0;
14688  else
14689  return SCIPvarGetNActiveConflicts(var->data.original.transvar, stat, dir);
14690 
14691  case SCIP_VARSTATUS_LOOSE:
14692  case SCIP_VARSTATUS_COLUMN:
14693  return SCIPhistoryGetNActiveConflicts(var->history, dir);
14694 
14695  case SCIP_VARSTATUS_FIXED:
14696  return 0;
14697 
14699  if( var->data.aggregate.scalar > 0.0 )
14700  return SCIPvarGetNActiveConflicts(var->data.aggregate.var, stat, dir);
14701  else
14703 
14705  return 0;
14706 
14709 
14710  default:
14711  SCIPerrorMessage("unknown variable status\n");
14712  SCIPABORT();
14713  return 0; /*lint !e527*/
14714  }
14715 }
14716 
14717 /** gets the number of active conflicts containing this variable in given direction
14718  * in the current run
14719  */
14721  SCIP_VAR* var, /**< problem variable */
14722  SCIP_STAT* stat, /**< problem statistics */
14723  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14724  )
14725 {
14726  assert(var != NULL);
14727  assert(stat != NULL);
14728  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14729 
14730  switch( SCIPvarGetStatus(var) )
14731  {
14733  if( var->data.original.transvar == NULL )
14734  return 0;
14735  else
14737 
14738  case SCIP_VARSTATUS_LOOSE:
14739  case SCIP_VARSTATUS_COLUMN:
14740  return SCIPhistoryGetNActiveConflicts(var->historycrun, dir);
14741 
14742  case SCIP_VARSTATUS_FIXED:
14743  return 0;
14744 
14746  if( var->data.aggregate.scalar > 0.0 )
14747  return SCIPvarGetNActiveConflictsCurrentRun(var->data.aggregate.var, stat, dir);
14748  else
14750 
14752  return 0;
14753 
14756 
14757  default:
14758  SCIPerrorMessage("unknown variable status\n");
14759  SCIPABORT();
14760  return 0; /*lint !e527*/
14761  }
14762 }
14763 
14764 /** gets the average conflict length in given direction due to branching on the variable */
14766  SCIP_VAR* var, /**< problem variable */
14767  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14768  )
14769 {
14770  assert(var != NULL);
14771  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14772 
14773  switch( SCIPvarGetStatus(var) )
14774  {
14776  if( var->data.original.transvar == NULL )
14777  return 0.0;
14778  else
14780 
14781  case SCIP_VARSTATUS_LOOSE:
14782  case SCIP_VARSTATUS_COLUMN:
14783  return SCIPhistoryGetAvgConflictlength(var->history, dir);
14784  case SCIP_VARSTATUS_FIXED:
14785  return 0.0;
14786 
14788  if( var->data.aggregate.scalar > 0.0 )
14789  return SCIPvarGetAvgConflictlength(var->data.aggregate.var, dir);
14790  else
14792 
14794  return 0.0;
14795 
14798 
14799  default:
14800  SCIPerrorMessage("unknown variable status\n");
14801  SCIPABORT();
14802  return 0.0; /*lint !e527*/
14803  }
14804 }
14805 
14806 /** gets the average conflict length in given direction due to branching on the variable
14807  * in the current run
14808  */
14810  SCIP_VAR* var, /**< problem variable */
14811  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
14812  )
14813 {
14814  assert(var != NULL);
14815  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14816 
14817  switch( SCIPvarGetStatus(var) )
14818  {
14820  if( var->data.original.transvar == NULL )
14821  return 0.0;
14822  else
14824 
14825  case SCIP_VARSTATUS_LOOSE:
14826  case SCIP_VARSTATUS_COLUMN:
14827  return SCIPhistoryGetAvgConflictlength(var->historycrun, dir);
14828 
14829  case SCIP_VARSTATUS_FIXED:
14830  return 0.0;
14831 
14833  if( var->data.aggregate.scalar > 0.0 )
14835  else
14837 
14839  return 0.0;
14840 
14843 
14844  default:
14845  SCIPerrorMessage("unknown variable status\n");
14846  SCIPABORT();
14847  return 0.0; /*lint !e527*/
14848  }
14849 }
14850 
14851 /** increases the number of branchings counter of the variable */
14853  SCIP_VAR* var, /**< problem variable */
14854  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14855  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14856  SCIP_STAT* stat, /**< problem statistics */
14857  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14858  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14859  int depth /**< depth at which the bound change took place */
14860  )
14861 {
14862  assert(var != NULL);
14863  assert(stat != NULL);
14864  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14865 
14866  /* check if history statistics should be collected for a variable */
14867  if( !stat->collectvarhistory )
14868  return SCIP_OKAY;
14869 
14870  switch( SCIPvarGetStatus(var) )
14871  {
14873  if( var->data.original.transvar == NULL )
14874  {
14875  SCIPerrorMessage("cannot update branching counter of original untransformed variable\n");
14876  return SCIP_INVALIDDATA;
14877  }
14878  SCIP_CALL( SCIPvarIncNBranchings(var->data.original.transvar, blkmem, set, stat, dir, value, depth) );
14879  return SCIP_OKAY;
14880 
14881  case SCIP_VARSTATUS_LOOSE:
14882  case SCIP_VARSTATUS_COLUMN:
14883  {
14884  SCIPhistoryIncNBranchings(var->history, dir, depth);
14885  SCIPhistoryIncNBranchings(var->historycrun, dir, depth);
14886  SCIPhistoryIncNBranchings(stat->glbhistory, dir, depth);
14887  SCIPhistoryIncNBranchings(stat->glbhistorycrun, dir, depth);
14888 
14889  if( useValuehistory(var, value, set) )
14890  {
14891  SCIP_HISTORY* history;
14892 
14893  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14894  assert(history != NULL);
14895 
14896  SCIPhistoryIncNBranchings(history, dir, depth);
14897  }
14898 
14899  return SCIP_OKAY;
14900  }
14901  case SCIP_VARSTATUS_FIXED:
14902  SCIPerrorMessage("cannot update branching counter of a fixed variable\n");
14903  return SCIP_INVALIDDATA;
14904 
14906  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14907 
14908  if( var->data.aggregate.scalar > 0.0 )
14909  {
14910  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, dir, value, depth) );
14911  }
14912  else
14913  {
14914  assert(var->data.aggregate.scalar < 0.0);
14915  SCIP_CALL( SCIPvarIncNBranchings(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14916  }
14917  return SCIP_OKAY;
14918 
14920  SCIPerrorMessage("cannot update branching counter of a multi-aggregated variable\n");
14921  return SCIP_INVALIDDATA;
14922 
14924  value = 1.0 - value;
14925 
14926  SCIP_CALL( SCIPvarIncNBranchings(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, depth) );
14927  return SCIP_OKAY;
14928 
14929  default:
14930  SCIPerrorMessage("unknown variable status\n");
14931  return SCIP_INVALIDDATA;
14932  }
14933 }
14934 
14935 /** increases the inference sum of the variable by the given weight */
14937  SCIP_VAR* var, /**< problem variable */
14938  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
14939  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
14940  SCIP_STAT* stat, /**< problem statistics */
14941  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
14942  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
14943  SCIP_Real weight /**< weight of this update in inference score */
14944  )
14945 {
14946  assert(var != NULL);
14947  assert(stat != NULL);
14948  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
14949 
14950  /* check if history statistics should be collected for a variable */
14951  if( !stat->collectvarhistory )
14952  return SCIP_OKAY;
14953 
14954  switch( SCIPvarGetStatus(var) )
14955  {
14957  if( var->data.original.transvar == NULL )
14958  {
14959  SCIPerrorMessage("cannot update inference counter of original untransformed variable\n");
14960  return SCIP_INVALIDDATA;
14961  }
14962  SCIP_CALL( SCIPvarIncInferenceSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
14963  return SCIP_OKAY;
14964 
14965  case SCIP_VARSTATUS_LOOSE:
14966  case SCIP_VARSTATUS_COLUMN:
14967  {
14968  SCIPhistoryIncInferenceSum(var->history, dir, weight);
14969  SCIPhistoryIncInferenceSum(var->historycrun, dir, weight);
14970  SCIPhistoryIncInferenceSum(stat->glbhistory, dir, weight);
14971  SCIPhistoryIncInferenceSum(stat->glbhistorycrun, dir, weight);
14972 
14973  if( useValuehistory(var, value, set) )
14974  {
14975  SCIP_HISTORY* history;
14976 
14977  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
14978  assert(history != NULL);
14979 
14980  SCIPhistoryIncInferenceSum(history, dir, weight);
14981  }
14982 
14983  return SCIP_OKAY;
14984  }
14985  case SCIP_VARSTATUS_FIXED:
14986  SCIPerrorMessage("cannot update inference counter of a fixed variable\n");
14987  return SCIP_INVALIDDATA;
14988 
14990  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
14991 
14992  if( var->data.aggregate.scalar > 0.0 )
14993  {
14994  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
14995  }
14996  else
14997  {
14998  assert(var->data.aggregate.scalar < 0.0);
14999  SCIP_CALL( SCIPvarIncInferenceSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15000  }
15001  return SCIP_OKAY;
15002 
15004  SCIPerrorMessage("cannot update inference counter of a multi-aggregated variable\n");
15005  return SCIP_INVALIDDATA;
15006 
15008  value = 1.0 - value;
15009 
15010  SCIP_CALL( SCIPvarIncInferenceSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15011  return SCIP_OKAY;
15012 
15013  default:
15014  SCIPerrorMessage("unknown variable status\n");
15015  return SCIP_INVALIDDATA;
15016  }
15017 }
15018 
15019 /** increases the cutoff sum of the variable by the given weight */
15021  SCIP_VAR* var, /**< problem variable */
15022  BMS_BLKMEM* blkmem, /**< block memory, or NULL if the domain value is SCIP_UNKNOWN */
15023  SCIP_SET* set, /**< global SCIP settings, or NULL if the domain value is SCIP_UNKNOWN */
15024  SCIP_STAT* stat, /**< problem statistics */
15025  SCIP_BRANCHDIR dir, /**< branching direction (downwards, or upwards) */
15026  SCIP_Real value, /**< domain value, or SCIP_UNKNOWN */
15027  SCIP_Real weight /**< weight of this update in cutoff score */
15028  )
15029 {
15030  assert(var != NULL);
15031  assert(stat != NULL);
15032  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15033 
15034  /* check if history statistics should be collected for a variable */
15035  if( !stat->collectvarhistory )
15036  return SCIP_OKAY;
15037 
15038  switch( SCIPvarGetStatus(var) )
15039  {
15041  if( var->data.original.transvar == NULL )
15042  {
15043  SCIPerrorMessage("cannot update cutoff sum of original untransformed variable\n");
15044  return SCIP_INVALIDDATA;
15045  }
15046  SCIP_CALL( SCIPvarIncCutoffSum(var->data.original.transvar, blkmem, set, stat, dir, value, weight) );
15047  return SCIP_OKAY;
15048 
15049  case SCIP_VARSTATUS_LOOSE:
15050  case SCIP_VARSTATUS_COLUMN:
15051  {
15052  SCIPhistoryIncCutoffSum(var->history, dir, weight);
15053  SCIPhistoryIncCutoffSum(var->historycrun, dir, weight);
15054  SCIPhistoryIncCutoffSum(stat->glbhistory, dir, weight);
15055  SCIPhistoryIncCutoffSum(stat->glbhistorycrun, dir, weight);
15056 
15057  if( useValuehistory(var, value, set) )
15058  {
15059  SCIP_HISTORY* history;
15060 
15061  SCIP_CALL( findValuehistoryEntry(var, value, blkmem, set, &history) );
15062  assert(history != NULL);
15063 
15064  SCIPhistoryIncCutoffSum(history, dir, weight);
15065  }
15066 
15067  return SCIP_OKAY;
15068  }
15069  case SCIP_VARSTATUS_FIXED:
15070  SCIPerrorMessage("cannot update cutoff sum of a fixed variable\n");
15071  return SCIP_INVALIDDATA;
15072 
15074  value = (value - var->data.aggregate.constant)/var->data.aggregate.scalar;
15075 
15076  if( var->data.aggregate.scalar > 0.0 )
15077  {
15078  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, dir, value, weight) );
15079  }
15080  else
15081  {
15082  assert(var->data.aggregate.scalar < 0.0);
15083  SCIP_CALL( SCIPvarIncCutoffSum(var->data.aggregate.var, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15084  }
15085  return SCIP_OKAY;
15086 
15088  SCIPerrorMessage("cannot update cutoff sum of a multi-aggregated variable\n");
15089  return SCIP_INVALIDDATA;
15090 
15092  value = 1.0 - value;
15093 
15094  SCIP_CALL( SCIPvarIncCutoffSum(var->negatedvar, blkmem, set, stat, SCIPbranchdirOpposite(dir), value, weight) );
15095  return SCIP_OKAY;
15096 
15097  default:
15098  SCIPerrorMessage("unknown variable status\n");
15099  return SCIP_INVALIDDATA;
15100  }
15101 }
15102 
15103 /** returns the number of times, a bound of the variable was changed in given direction due to branching */
15105  SCIP_VAR* var, /**< problem variable */
15106  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15107  )
15108 {
15109  assert(var != NULL);
15110  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15111 
15112  switch( SCIPvarGetStatus(var) )
15113  {
15115  if( var->data.original.transvar == NULL )
15116  return 0;
15117  else
15118  return SCIPvarGetNBranchings(var->data.original.transvar, dir);
15119 
15120  case SCIP_VARSTATUS_LOOSE:
15121  case SCIP_VARSTATUS_COLUMN:
15122  return SCIPhistoryGetNBranchings(var->history, dir);
15123 
15124  case SCIP_VARSTATUS_FIXED:
15125  return 0;
15126 
15128  if( var->data.aggregate.scalar > 0.0 )
15129  return SCIPvarGetNBranchings(var->data.aggregate.var, dir);
15130  else
15132 
15134  return 0;
15135 
15138 
15139  default:
15140  SCIPerrorMessage("unknown variable status\n");
15141  SCIPABORT();
15142  return 0; /*lint !e527*/
15143  }
15144 }
15145 
15146 /** returns the number of times, a bound of the variable was changed in given direction due to branching
15147  * in the current run
15148  */
15150  SCIP_VAR* var, /**< problem variable */
15151  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15152  )
15153 {
15154  assert(var != NULL);
15155  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15156 
15157  switch( SCIPvarGetStatus(var) )
15158  {
15160  if( var->data.original.transvar == NULL )
15161  return 0;
15162  else
15164 
15165  case SCIP_VARSTATUS_LOOSE:
15166  case SCIP_VARSTATUS_COLUMN:
15167  return SCIPhistoryGetNBranchings(var->historycrun, dir);
15168 
15169  case SCIP_VARSTATUS_FIXED:
15170  return 0;
15171 
15173  if( var->data.aggregate.scalar > 0.0 )
15175  else
15177 
15179  return 0;
15180 
15183 
15184  default:
15185  SCIPerrorMessage("unknown variable status\n");
15186  SCIPABORT();
15187  return 0; /*lint !e527*/
15188  }
15189 }
15190 
15191 /** returns the average depth of bound changes in given direction due to branching on the variable */
15193  SCIP_VAR* var, /**< problem variable */
15194  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15195  )
15196 {
15197  assert(var != NULL);
15198  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15199 
15200  switch( SCIPvarGetStatus(var) )
15201  {
15203  if( var->data.original.transvar == NULL )
15204  return 0.0;
15205  else
15206  return SCIPvarGetAvgBranchdepth(var->data.original.transvar, dir);
15207 
15208  case SCIP_VARSTATUS_LOOSE:
15209  case SCIP_VARSTATUS_COLUMN:
15210  return SCIPhistoryGetAvgBranchdepth(var->history, dir);
15211 
15212  case SCIP_VARSTATUS_FIXED:
15213  return 0.0;
15214 
15216  if( var->data.aggregate.scalar > 0.0 )
15217  return SCIPvarGetAvgBranchdepth(var->data.aggregate.var, dir);
15218  else
15220 
15222  return 0.0;
15223 
15226 
15227  default:
15228  SCIPerrorMessage("unknown variable status\n");
15229  SCIPABORT();
15230  return 0.0; /*lint !e527*/
15231  }
15232 }
15233 
15234 /** returns the average depth of bound changes in given direction due to branching on the variable
15235  * in the current run
15236  */
15238  SCIP_VAR* var, /**< problem variable */
15239  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15240  )
15241 {
15242  assert(var != NULL);
15243  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15244 
15245  switch( SCIPvarGetStatus(var) )
15246  {
15248  if( var->data.original.transvar == NULL )
15249  return 0.0;
15250  else
15252 
15253  case SCIP_VARSTATUS_LOOSE:
15254  case SCIP_VARSTATUS_COLUMN:
15255  return SCIPhistoryGetAvgBranchdepth(var->historycrun, dir);
15256 
15257  case SCIP_VARSTATUS_FIXED:
15258  return 0.0;
15259 
15261  if( var->data.aggregate.scalar > 0.0 )
15263  else
15266 
15268  return 0.0;
15269 
15272  dir == SCIP_BRANCHDIR_DOWNWARDS ? SCIP_BRANCHDIR_UPWARDS : SCIP_BRANCHDIR_DOWNWARDS);
15273 
15274  default:
15275  SCIPerrorMessage("unknown variable status\n");
15276  SCIPABORT();
15277  return 0.0; /*lint !e527*/
15278  }
15279 }
15280 
15281 /** returns the variable's VSIDS score */
15283  SCIP_VAR* var, /**< problem variable */
15284  SCIP_STAT* stat, /**< problem statistics */
15285  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15286  )
15287 {
15288  assert(var != NULL);
15289  assert(stat != NULL);
15290  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15291 
15293  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15294 
15295  switch( SCIPvarGetStatus(var) )
15296  {
15298  if( var->data.original.transvar == NULL )
15299  return 0.0;
15300  else
15301  return SCIPvarGetVSIDS(var->data.original.transvar, stat, dir);
15302 
15303  case SCIP_VARSTATUS_LOOSE:
15304  case SCIP_VARSTATUS_COLUMN:
15305  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_LOOSE); /* column case already handled in if condition above */
15306  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
15307 
15308  case SCIP_VARSTATUS_FIXED:
15309  return 0.0;
15310 
15312  if( var->data.aggregate.scalar > 0.0 )
15313  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, dir);
15314  else
15315  return SCIPvarGetVSIDS(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15316 
15318  return 0.0;
15319 
15321  return SCIPvarGetVSIDS(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15322 
15323  default:
15324  SCIPerrorMessage("unknown variable status\n");
15325  SCIPABORT();
15326  return 0.0; /*lint !e527*/
15327  }
15328 }
15329 
15330 /** returns the variable's VSIDS score only using conflicts of the current run */
15332  SCIP_VAR* var, /**< problem variable */
15333  SCIP_STAT* stat, /**< problem statistics */
15334  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15335  )
15336 {
15337  assert(var != NULL);
15338  assert(stat != NULL);
15339  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15340 
15341  if( dir != SCIP_BRANCHDIR_DOWNWARDS && dir != SCIP_BRANCHDIR_UPWARDS )
15342  {
15343  SCIPerrorMessage("invalid branching direction %d when asking for VSIDS value\n", dir);
15344  return SCIP_INVALID;
15345  }
15346 
15347  switch( SCIPvarGetStatus(var) )
15348  {
15350  if( var->data.original.transvar == NULL )
15351  return 0.0;
15352  else
15353  return SCIPvarGetVSIDSCurrentRun(var->data.original.transvar, stat, dir);
15354 
15355  case SCIP_VARSTATUS_LOOSE:
15356  case SCIP_VARSTATUS_COLUMN:
15357  return SCIPhistoryGetVSIDS(var->historycrun, dir)/stat->vsidsweight;
15358 
15359  case SCIP_VARSTATUS_FIXED:
15360  return 0.0;
15361 
15363  if( var->data.aggregate.scalar > 0.0 )
15364  return SCIPvarGetVSIDSCurrentRun(var->data.aggregate.var, stat, dir);
15365  else
15367 
15369  return 0.0;
15370 
15373 
15374  default:
15375  SCIPerrorMessage("unknown variable status\n");
15376  SCIPABORT();
15377  return 0.0; /*lint !e527*/
15378  }
15379 }
15380 
15381 /** returns the number of inferences branching on this variable in given direction triggered */
15383  SCIP_VAR* var, /**< problem variable */
15384  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15385  )
15386 {
15387  assert(var != NULL);
15388  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15389 
15390  switch( SCIPvarGetStatus(var) )
15391  {
15393  if( var->data.original.transvar == NULL )
15394  return 0.0;
15395  else
15396  return SCIPvarGetInferenceSum(var->data.original.transvar, dir);
15397 
15398  case SCIP_VARSTATUS_LOOSE:
15399  case SCIP_VARSTATUS_COLUMN:
15400  return SCIPhistoryGetInferenceSum(var->history, dir);
15401 
15402  case SCIP_VARSTATUS_FIXED:
15403  return 0.0;
15404 
15406  if( var->data.aggregate.scalar > 0.0 )
15407  return SCIPvarGetInferenceSum(var->data.aggregate.var, dir);
15408  else
15410 
15412  return 0.0;
15413 
15416 
15417  default:
15418  SCIPerrorMessage("unknown variable status\n");
15419  SCIPABORT();
15420  return 0.0; /*lint !e527*/
15421  }
15422 }
15423 
15424 /** returns the number of inferences branching on this variable in given direction triggered
15425  * in the current run
15426  */
15428  SCIP_VAR* var, /**< problem variable */
15429  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15430  )
15431 {
15432  assert(var != NULL);
15433  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15434 
15435  switch( SCIPvarGetStatus(var) )
15436  {
15438  if( var->data.original.transvar == NULL )
15439  return 0.0;
15440  else
15442 
15443  case SCIP_VARSTATUS_LOOSE:
15444  case SCIP_VARSTATUS_COLUMN:
15445  return SCIPhistoryGetInferenceSum(var->historycrun, dir);
15446 
15447  case SCIP_VARSTATUS_FIXED:
15448  return 0.0;
15449 
15451  if( var->data.aggregate.scalar > 0.0 )
15453  else
15455 
15457  return 0.0;
15458 
15461 
15462  default:
15463  SCIPerrorMessage("unknown variable status\n");
15464  SCIPABORT();
15465  return 0.0; /*lint !e527*/
15466  }
15467 }
15468 
15469 /** returns the average number of inferences found after branching on the variable in given direction */
15471  SCIP_VAR* var, /**< problem variable */
15472  SCIP_STAT* stat, /**< problem statistics */
15473  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15474  )
15475 {
15476  assert(var != NULL);
15477  assert(stat != 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 SCIPhistoryGetAvgInferences(stat->glbhistory, dir);
15485  else
15486  return SCIPvarGetAvgInferences(var->data.original.transvar, stat, dir);
15487 
15488  case SCIP_VARSTATUS_LOOSE:
15489  case SCIP_VARSTATUS_COLUMN:
15490  if( SCIPhistoryGetNBranchings(var->history, dir) > 0 )
15491  return SCIPhistoryGetAvgInferences(var->history, dir);
15492  else
15493  {
15494  int nimpls;
15495  int ncliques;
15496 
15497  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15498  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15499  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistory, dir); /*lint !e790*/
15500  }
15501 
15502  case SCIP_VARSTATUS_FIXED:
15503  return 0.0;
15504 
15506  if( var->data.aggregate.scalar > 0.0 )
15507  return SCIPvarGetAvgInferences(var->data.aggregate.var, stat, dir);
15508  else
15510 
15512  return 0.0;
15513 
15515  return SCIPvarGetAvgInferences(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15516 
15517  default:
15518  SCIPerrorMessage("unknown variable status\n");
15519  SCIPABORT();
15520  return 0.0; /*lint !e527*/
15521  }
15522 }
15523 
15524 /** returns the average number of inferences found after branching on the variable in given direction
15525  * in the current run
15526  */
15528  SCIP_VAR* var, /**< problem variable */
15529  SCIP_STAT* stat, /**< problem statistics */
15530  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15531  )
15532 {
15533  assert(var != NULL);
15534  assert(stat != NULL);
15535  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15536 
15537  switch( SCIPvarGetStatus(var) )
15538  {
15540  if( var->data.original.transvar == NULL )
15541  return SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir);
15542  else
15543  return SCIPvarGetAvgInferencesCurrentRun(var->data.original.transvar, stat, dir);
15544 
15545  case SCIP_VARSTATUS_LOOSE:
15546  case SCIP_VARSTATUS_COLUMN:
15547  if( SCIPhistoryGetNBranchings(var->historycrun, dir) > 0 )
15548  return SCIPhistoryGetAvgInferences(var->historycrun, dir);
15549  else
15550  {
15551  int nimpls;
15552  int ncliques;
15553 
15554  nimpls = SCIPvarGetNImpls(var, dir == SCIP_BRANCHDIR_UPWARDS);
15555  ncliques = SCIPvarGetNCliques(var, dir == SCIP_BRANCHDIR_UPWARDS);
15556  return nimpls + ncliques > 0 ? (SCIP_Real)(nimpls + 2*ncliques) : SCIPhistoryGetAvgInferences(stat->glbhistorycrun, dir); /*lint !e790*/
15557  }
15558 
15559  case SCIP_VARSTATUS_FIXED:
15560  return 0.0;
15561 
15563  if( var->data.aggregate.scalar > 0.0 )
15564  return SCIPvarGetAvgInferencesCurrentRun(var->data.aggregate.var, stat, dir);
15565  else
15567 
15569  return 0.0;
15570 
15573 
15574  default:
15575  SCIPerrorMessage("unknown variable status\n");
15576  SCIPABORT();
15577  return 0.0; /*lint !e527*/
15578  }
15579 }
15580 
15581 /** returns the number of cutoffs branching on this variable in given direction produced */
15583  SCIP_VAR* var, /**< problem variable */
15584  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15585  )
15586 {
15587  assert(var != NULL);
15588  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15589 
15590  switch( SCIPvarGetStatus(var) )
15591  {
15593  if( var->data.original.transvar == NULL )
15594  return 0;
15595  else
15596  return SCIPvarGetCutoffSum(var->data.original.transvar, dir);
15597 
15598  case SCIP_VARSTATUS_LOOSE:
15599  case SCIP_VARSTATUS_COLUMN:
15600  return SCIPhistoryGetCutoffSum(var->history, dir);
15601 
15602  case SCIP_VARSTATUS_FIXED:
15603  return 0;
15604 
15606  if( var->data.aggregate.scalar > 0.0 )
15607  return SCIPvarGetCutoffSum(var->data.aggregate.var, dir);
15608  else
15610 
15612  return 0;
15613 
15616 
15617  default:
15618  SCIPerrorMessage("unknown variable status\n");
15619  SCIPABORT();
15620  return 0; /*lint !e527*/
15621  }
15622 }
15623 
15624 /** returns the number of cutoffs branching on this variable in given direction produced in the current run */
15626  SCIP_VAR* var, /**< problem variable */
15627  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15628  )
15629 {
15630  assert(var != NULL);
15631  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15632 
15633  switch( SCIPvarGetStatus(var) )
15634  {
15636  if( var->data.original.transvar == NULL )
15637  return 0;
15638  else
15640 
15641  case SCIP_VARSTATUS_LOOSE:
15642  case SCIP_VARSTATUS_COLUMN:
15643  return SCIPhistoryGetCutoffSum(var->historycrun, dir);
15644 
15645  case SCIP_VARSTATUS_FIXED:
15646  return 0;
15647 
15649  if( var->data.aggregate.scalar > 0.0 )
15650  return SCIPvarGetCutoffSumCurrentRun(var->data.aggregate.var, dir);
15651  else
15653 
15655  return 0;
15656 
15659 
15660  default:
15661  SCIPerrorMessage("unknown variable status\n");
15662  SCIPABORT();
15663  return 0; /*lint !e527*/
15664  }
15665 }
15666 
15667 /** returns the average number of cutoffs found after branching on the variable in given direction */
15669  SCIP_VAR* var, /**< problem variable */
15670  SCIP_STAT* stat, /**< problem statistics */
15671  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15672  )
15673 {
15674  assert(var != NULL);
15675  assert(stat != NULL);
15676  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15677 
15678  switch( SCIPvarGetStatus(var) )
15679  {
15681  if( var->data.original.transvar == NULL )
15682  return SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15683  else
15684  return SCIPvarGetAvgCutoffs(var->data.original.transvar, stat, dir);
15685 
15686  case SCIP_VARSTATUS_LOOSE:
15687  case SCIP_VARSTATUS_COLUMN:
15688  return SCIPhistoryGetNBranchings(var->history, dir) > 0
15689  ? SCIPhistoryGetAvgCutoffs(var->history, dir)
15690  : SCIPhistoryGetAvgCutoffs(stat->glbhistory, dir);
15691 
15692  case SCIP_VARSTATUS_FIXED:
15693  return 0.0;
15694 
15696  if( var->data.aggregate.scalar > 0.0 )
15697  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, dir);
15698  else
15699  return SCIPvarGetAvgCutoffs(var->data.aggregate.var, stat, SCIPbranchdirOpposite(dir));
15700 
15702  return 0.0;
15703 
15705  return SCIPvarGetAvgCutoffs(var->negatedvar, stat, SCIPbranchdirOpposite(dir));
15706 
15707  default:
15708  SCIPerrorMessage("unknown variable status\n");
15709  SCIPABORT();
15710  return 0.0; /*lint !e527*/
15711  }
15712 }
15713 
15714 /** returns the average number of cutoffs found after branching on the variable in given direction in the current run */
15716  SCIP_VAR* var, /**< problem variable */
15717  SCIP_STAT* stat, /**< problem statistics */
15718  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
15719  )
15720 {
15721  assert(var != NULL);
15722  assert(stat != NULL);
15723  assert(dir == SCIP_BRANCHDIR_DOWNWARDS || dir == SCIP_BRANCHDIR_UPWARDS);
15724 
15725  switch( SCIPvarGetStatus(var) )
15726  {
15728  if( var->data.original.transvar == NULL )
15729  return SCIPhistoryGetAvgCutoffs(stat->glbhistorycrun, dir);
15730  else
15731  return SCIPvarGetAvgCutoffsCurrentRun(var->data.original.transvar, stat, dir);
15732 
15733  case SCIP_VARSTATUS_LOOSE:
15734  case SCIP_VARSTATUS_COLUMN:
15735  return SCIPhistoryGetNBranchings(var->historycrun, dir) > 0
15738 
15739  case SCIP_VARSTATUS_FIXED:
15740  return 0.0;
15741 
15743  if( var->data.aggregate.scalar > 0.0 )
15744  return SCIPvarGetAvgCutoffsCurrentRun(var->data.aggregate.var, stat, dir);
15745  else
15747 
15749  return 0.0;
15750 
15753 
15754  default:
15755  SCIPerrorMessage("unknown variable status\n");
15756  SCIPABORT();
15757  return 0.0; /*lint !e527*/
15758  }
15759 }
15760 
15761 
15762 
15763 
15764 /*
15765  * information methods for bound changes
15766  */
15767 
15768 /** creates an artificial bound change information object with depth = INT_MAX and pos = -1 */
15770  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15771  BMS_BLKMEM* blkmem, /**< block memory */
15772  SCIP_VAR* var, /**< active variable that changed the bounds */
15773  SCIP_BOUNDTYPE boundtype, /**< type of bound for var: lower or upper bound */
15774  SCIP_Real oldbound, /**< old value for bound */
15775  SCIP_Real newbound /**< new value for bound */
15776  )
15777 {
15778  assert(bdchginfo != NULL);
15779 
15780  SCIP_ALLOC( BMSallocBlockMemory(blkmem, bdchginfo) );
15781  (*bdchginfo)->oldbound = oldbound;
15782  (*bdchginfo)->newbound = newbound;
15783  (*bdchginfo)->var = var;
15784  (*bdchginfo)->inferencedata.var = var;
15785  (*bdchginfo)->inferencedata.reason.prop = NULL;
15786  (*bdchginfo)->inferencedata.info = 0;
15787  (*bdchginfo)->bdchgidx.depth = INT_MAX;
15788  (*bdchginfo)->bdchgidx.pos = -1;
15789  (*bdchginfo)->pos = 0;
15790  (*bdchginfo)->boundchgtype = SCIP_BOUNDCHGTYPE_BRANCHING; /*lint !e641*/
15791  (*bdchginfo)->boundtype = boundtype; /*lint !e641*/
15792  (*bdchginfo)->inferboundtype = boundtype; /*lint !e641*/
15793  (*bdchginfo)->redundant = FALSE;
15794 
15795  return SCIP_OKAY;
15796 }
15797 
15798 /** frees a bound change information object */
15799 void SCIPbdchginfoFree(
15800  SCIP_BDCHGINFO** bdchginfo, /**< pointer to store bound change information */
15801  BMS_BLKMEM* blkmem /**< block memory */
15802  )
15803 {
15804  assert(bdchginfo != NULL);
15805 
15806  BMSfreeBlockMemory(blkmem, bdchginfo);
15807 }
15808 
15809 /** returns the bound change information for the last lower bound change on given active problem variable before or
15810  * after the bound change with the given index was applied;
15811  * returns NULL, if no change to the lower bound was applied up to this point of time
15812  */
15814  SCIP_VAR* var, /**< active problem variable */
15815  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15816  SCIP_Bool after /**< should the bound change with given index be included? */
15817  )
15818 {
15819  int i;
15820 
15821  assert(var != NULL);
15822  assert(SCIPvarIsActive(var));
15823 
15824  /* search the correct bound change information for the given bound change index */
15825  if( after )
15826  {
15827  for( i = var->nlbchginfos-1; i >= 0; --i )
15828  {
15829  assert(var->lbchginfos[i].var == var);
15831  assert(var->lbchginfos[i].pos == i);
15832 
15833  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15834  if( var->lbchginfos[i].redundant )
15835  return NULL;
15836  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15837 
15838  /* if we reached the bound change index, return the current bound change info */
15839  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->lbchginfos[i].bdchgidx) )
15840  return &var->lbchginfos[i];
15841  }
15842  }
15843  else
15844  {
15845  for( i = var->nlbchginfos-1; i >= 0; --i )
15846  {
15847  assert(var->lbchginfos[i].var == var);
15849  assert(var->lbchginfos[i].pos == i);
15850 
15851  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15852  if( var->lbchginfos[i].redundant )
15853  return NULL;
15854  assert(var->lbchginfos[i].oldbound < var->lbchginfos[i].newbound);
15855 
15856  /* if we reached the bound change index, return the current bound change info */
15857  if( SCIPbdchgidxIsEarlier(&var->lbchginfos[i].bdchgidx, bdchgidx) )
15858  return &var->lbchginfos[i];
15859  }
15860  }
15861 
15862  return NULL;
15863 }
15864 
15865 /** returns the bound change information for the last upper bound change on given active problem variable before or
15866  * after the bound change with the given index was applied;
15867  * returns NULL, if no change to the upper bound was applied up to this point of time
15868  */
15870  SCIP_VAR* var, /**< active problem variable */
15871  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15872  SCIP_Bool after /**< should the bound change with given index be included? */
15873  )
15874 {
15875  int i;
15876 
15877  assert(var != NULL);
15878  assert(SCIPvarIsActive(var));
15879 
15880  /* search the correct bound change information for the given bound change index */
15881  if( after )
15882  {
15883  for( i = var->nubchginfos-1; i >= 0; --i )
15884  {
15885  assert(var->ubchginfos[i].var == var);
15887  assert(var->ubchginfos[i].pos == i);
15888 
15889  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15890  if( var->ubchginfos[i].redundant )
15891  return NULL;
15892  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15893 
15894  /* if we reached the bound change index, return the current bound change info */
15895  if( !SCIPbdchgidxIsEarlier(bdchgidx, &var->ubchginfos[i].bdchgidx) )
15896  return &var->ubchginfos[i];
15897  }
15898  }
15899  else
15900  {
15901  for( i = var->nubchginfos-1; i >= 0; --i )
15902  {
15903  assert(var->ubchginfos[i].var == var);
15905  assert(var->ubchginfos[i].pos == i);
15906 
15907  /* if we reached the (due to global bounds) redundant bound changes, return NULL */
15908  if( var->ubchginfos[i].redundant )
15909  return NULL;
15910  assert(var->ubchginfos[i].oldbound > var->ubchginfos[i].newbound);
15911 
15912  /* if we reached the bound change index, return the current bound change info */
15913  if( SCIPbdchgidxIsEarlier(&var->ubchginfos[i].bdchgidx, bdchgidx) )
15914  return &var->ubchginfos[i];
15915  }
15916  }
15917 
15918  return NULL;
15919 }
15920 
15921 /** returns the bound change information for the last lower or upper bound change on given active problem variable
15922  * before or after the bound change with the given index was applied;
15923  * returns NULL, if no change to the lower/upper bound was applied up to this point of time
15924  */
15926  SCIP_VAR* var, /**< active problem variable */
15927  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
15928  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15929  SCIP_Bool after /**< should the bound change with given index be included? */
15930  )
15931 {
15932  if( boundtype == SCIP_BOUNDTYPE_LOWER )
15933  return SCIPvarGetLbchgInfo(var, bdchgidx, after);
15934  else
15935  {
15936  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
15937  return SCIPvarGetUbchgInfo(var, bdchgidx, after);
15938  }
15939 }
15940 
15941 /** returns lower bound of variable directly before or after the bound change given by the bound change index
15942  * was applied
15943  *
15944  * @deprecated Please use SCIPgetVarLbAtIndex()
15945  */
15947  SCIP_VAR* var, /**< problem variable */
15948  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
15949  SCIP_Bool after /**< should the bound change with given index be included? */
15950  )
15951 {
15952  SCIP_VARSTATUS varstatus;
15953  assert(var != NULL);
15954 
15955  varstatus = SCIPvarGetStatus(var);
15956 
15957  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
15958  {
15959  if( bdchgidx == NULL )
15960  return SCIPvarGetLbLocal(var);
15961  else
15962  {
15963  SCIP_BDCHGINFO* bdchginfo;
15964 
15965  bdchginfo = SCIPvarGetLbchgInfo(var, bdchgidx, after);
15966  if( bdchginfo != NULL )
15967  return SCIPbdchginfoGetNewbound(bdchginfo);
15968  else
15969  return var->glbdom.lb;
15970  }
15971  }
15972 
15973  /* get bounds of attached variables */
15974  switch( varstatus )
15975  {
15977  assert(var->data.original.transvar != NULL);
15978  return SCIPvarGetLbAtIndex(var->data.original.transvar, bdchgidx, after);
15979 
15980  case SCIP_VARSTATUS_FIXED:
15981  return var->glbdom.lb;
15982 
15983  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
15984  assert(var->data.aggregate.var != NULL);
15985  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
15986  * corresponding infinity value instead of performing an arithmetical transformation (compare method
15987  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
15988  * (or is called by) a public interface method; instead, we only assert that values are finite
15989  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
15990  * positives and negatives if the parameter <numerics/infinity> is modified by the user
15991  */
15992  if( var->data.aggregate.scalar > 0.0 )
15993  {
15994  /* a > 0 -> get lower bound of y */
15995  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
15996  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
15997  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
15998  + var->data.aggregate.constant;
15999  }
16000  else if( var->data.aggregate.scalar < 0.0 )
16001  {
16002  /* a < 0 -> get upper bound of y */
16003  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16004  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16005  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16006  + var->data.aggregate.constant;
16007  }
16008  else
16009  {
16010  SCIPerrorMessage("scalar is zero in aggregation\n");
16011  SCIPABORT();
16012  return SCIP_INVALID; /*lint !e527*/
16013  }
16014 
16016  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16017  if ( var->data.multaggr.nvars == 1 )
16018  {
16019  assert(var->data.multaggr.vars != NULL);
16020  assert(var->data.multaggr.scalars != NULL);
16021  assert(var->data.multaggr.vars[0] != NULL);
16022 
16023  if( var->data.multaggr.scalars[0] > 0.0 )
16024  {
16025  /* a > 0 -> get lower bound of y */
16026  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16027  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16028  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16029  + var->data.multaggr.constant;
16030  }
16031  else if( var->data.multaggr.scalars[0] < 0.0 )
16032  {
16033  /* a < 0 -> get upper bound of y */
16034  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16035  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16036  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16037  + var->data.multaggr.constant;
16038  }
16039  else
16040  {
16041  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16042  SCIPABORT();
16043  return SCIP_INVALID; /*lint !e527*/
16044  }
16045  }
16046  SCIPerrorMessage("cannot get the bounds of a multi-aggregated variable.\n");
16047  SCIPABORT();
16048  return SCIP_INVALID; /*lint !e527*/
16049 
16050  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16051  assert(var->negatedvar != NULL);
16053  assert(var->negatedvar->negatedvar == var);
16054  return var->data.negate.constant - SCIPvarGetUbAtIndex(var->negatedvar, bdchgidx, after);
16055 
16056  case SCIP_VARSTATUS_COLUMN: /* for lint */
16057  case SCIP_VARSTATUS_LOOSE: /* for lint */
16058  default:
16059  SCIPerrorMessage("unknown variable status\n");
16060  SCIPABORT();
16061  return SCIP_INVALID; /*lint !e527*/
16062  }
16063 }
16064 
16065 /** returns upper bound of variable directly before or after the bound change given by the bound change index
16066  * was applied
16067  *
16068  * @deprecated Please use SCIPgetVarUbAtIndex()
16069  */
16071  SCIP_VAR* var, /**< problem variable */
16072  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16073  SCIP_Bool after /**< should the bound change with given index be included? */
16074  )
16075 {
16076  SCIP_VARSTATUS varstatus;
16077  assert(var != NULL);
16078 
16079  varstatus = SCIPvarGetStatus(var);
16080 
16081  if( varstatus == SCIP_VARSTATUS_COLUMN || varstatus == SCIP_VARSTATUS_LOOSE )
16082  {
16083  if( bdchgidx == NULL )
16084  return SCIPvarGetUbLocal(var);
16085  else
16086  {
16087  SCIP_BDCHGINFO* bdchginfo;
16088 
16089  bdchginfo = SCIPvarGetUbchgInfo(var, bdchgidx, after);
16090  if( bdchginfo != NULL )
16091  return SCIPbdchginfoGetNewbound(bdchginfo);
16092  else
16093  return var->glbdom.ub;
16094  }
16095  }
16096 
16097  /* get bounds of attached variables */
16098  switch( varstatus )
16099  {
16101  assert(var->data.original.transvar != NULL);
16102  return SCIPvarGetUbAtIndex(var->data.original.transvar, bdchgidx, after);
16103 
16104  case SCIP_VARSTATUS_FIXED:
16105  return var->glbdom.ub;
16106 
16107  case SCIP_VARSTATUS_AGGREGATED: /* x = a*y + c -> y = (x-c)/a */
16108  assert(var->data.aggregate.var != NULL);
16109  /* a correct implementation would need to check the value of var->data.aggregate.var for infinity and return the
16110  * corresponding infinity value instead of performing an arithmetical transformation (compare method
16111  * SCIPvarGetLbLP()); however, we do not want to introduce a SCIP or SCIP_SET pointer to this method, since it is
16112  * (or is called by) a public interface method; instead, we only assert that values are finite
16113  * w.r.t. SCIP_DEFAULT_INFINITY, which seems to be true in our regression tests; note that this may yield false
16114  * positives and negatives if the parameter <numerics/infinity> is modified by the user
16115  */
16116  if( var->data.aggregate.scalar > 0.0 )
16117  {
16118  /* a > 0 -> get lower bound of y */
16119  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16120  assert(SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16121  return var->data.aggregate.scalar * SCIPvarGetUbAtIndex(var->data.aggregate.var, bdchgidx, after)
16122  + var->data.aggregate.constant;
16123  }
16124  else if( var->data.aggregate.scalar < 0.0 )
16125  {
16126  /* a < 0 -> get upper bound of y */
16127  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16128  assert(SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16129  return var->data.aggregate.scalar * SCIPvarGetLbAtIndex(var->data.aggregate.var, bdchgidx, after)
16130  + var->data.aggregate.constant;
16131  }
16132  else
16133  {
16134  SCIPerrorMessage("scalar is zero in aggregation\n");
16135  SCIPABORT();
16136  return SCIP_INVALID; /*lint !e527*/
16137  }
16138 
16140  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
16141  if ( var->data.multaggr.nvars == 1 )
16142  {
16143  assert(var->data.multaggr.vars != NULL);
16144  assert(var->data.multaggr.scalars != NULL);
16145  assert(var->data.multaggr.vars[0] != NULL);
16146 
16147  if( var->data.multaggr.scalars[0] > 0.0 )
16148  {
16149  /* a > 0 -> get lower bound of y */
16150  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16151  assert(SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16152  return var->data.multaggr.scalars[0] * SCIPvarGetUbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16153  + var->data.multaggr.constant;
16154  }
16155  else if( var->data.multaggr.scalars[0] < 0.0 )
16156  {
16157  /* a < 0 -> get upper bound of y */
16158  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) > -SCIP_DEFAULT_INFINITY);
16159  assert(SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after) < +SCIP_DEFAULT_INFINITY);
16160  return var->data.multaggr.scalars[0] * SCIPvarGetLbAtIndex(var->data.multaggr.vars[0], bdchgidx, after)
16161  + var->data.multaggr.constant;
16162  }
16163  else
16164  {
16165  SCIPerrorMessage("scalar is zero in multi-aggregation\n");
16166  SCIPABORT();
16167  return SCIP_INVALID; /*lint !e527*/
16168  }
16169  }
16170  SCIPerrorMessage("cannot get the bounds of a multiple aggregated variable.\n");
16171  SCIPABORT();
16172  return SCIP_INVALID; /*lint !e527*/
16173 
16174  case SCIP_VARSTATUS_NEGATED: /* x' = offset - x -> x = offset - x' */
16175  assert(var->negatedvar != NULL);
16177  assert(var->negatedvar->negatedvar == var);
16178  return var->data.negate.constant - SCIPvarGetLbAtIndex(var->negatedvar, bdchgidx, after);
16179 
16180  case SCIP_VARSTATUS_COLUMN: /* for lint */
16181  case SCIP_VARSTATUS_LOOSE: /* for lint */
16182  default:
16183  SCIPerrorMessage("unknown variable status\n");
16184  SCIPABORT();
16185  return SCIP_INVALID; /*lint !e527*/
16186  }
16187 }
16188 
16189 /** returns lower or upper bound of variable directly before or after the bound change given by the bound change index
16190  * was applied
16191  *
16192  * @deprecated Please use SCIPgetVarBdAtIndex()
16193  */
16195  SCIP_VAR* var, /**< problem variable */
16196  SCIP_BOUNDTYPE boundtype, /**< type of bound: lower or upper bound */
16197  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16198  SCIP_Bool after /**< should the bound change with given index be included? */
16199  )
16200 {
16201  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16202  return SCIPvarGetLbAtIndex(var, bdchgidx, after);
16203  else
16204  {
16205  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16206  return SCIPvarGetUbAtIndex(var, bdchgidx, after);
16207  }
16208 }
16209 
16210 /** returns whether the binary variable was fixed at the time given by the bound change index
16211  *
16212  * @deprecated Please use SCIPgetVarWasFixedAtIndex()
16213  */
16215  SCIP_VAR* var, /**< problem variable */
16216  SCIP_BDCHGIDX* bdchgidx, /**< bound change index representing time on path to current node */
16217  SCIP_Bool after /**< should the bound change with given index be included? */
16218  )
16219 {
16220  assert(var != NULL);
16221  assert(SCIPvarIsBinary(var));
16222 
16223  /* check the current bounds first in order to decide at which bound change information we have to look
16224  * (which is expensive because we have to follow the aggregation tree to the active variable)
16225  */
16226  return ((SCIPvarGetLbLocal(var) > 0.5 && SCIPvarGetLbAtIndex(var, bdchgidx, after) > 0.5)
16227  || (SCIPvarGetUbLocal(var) < 0.5 && SCIPvarGetUbAtIndex(var, bdchgidx, after) < 0.5));
16228 }
16229 
16230 /** bound change index representing the initial time before any bound changes took place */
16231 static SCIP_BDCHGIDX initbdchgidx = {-2, 0};
16233 /** bound change index representing the presolving stage */
16234 static SCIP_BDCHGIDX presolvebdchgidx = {-1, 0};
16236 /** returns the last bound change index, at which the bounds of the given variable were tightened */
16238  SCIP_VAR* var /**< problem variable */
16239  )
16240 {
16241  SCIP_BDCHGIDX* lbchgidx;
16242  SCIP_BDCHGIDX* ubchgidx;
16243 
16244  assert(var != NULL);
16245 
16246  var = SCIPvarGetProbvar(var);
16247 
16248  /* check, if variable is original without transformed variable */
16249  if( var == NULL )
16250  return &initbdchgidx;
16251 
16252  /* check, if variable was fixed in presolving */
16253  if( !SCIPvarIsActive(var) )
16254  return &presolvebdchgidx;
16255 
16257 
16258  /* get depths of last bound change information for the lower and upper bound */
16259  lbchgidx = (var->nlbchginfos > 0 && !var->lbchginfos[var->nlbchginfos-1].redundant
16260  ? &var->lbchginfos[var->nlbchginfos-1].bdchgidx : &initbdchgidx);
16261  ubchgidx = (var->nubchginfos > 0 && !var->ubchginfos[var->nubchginfos-1].redundant
16262  ? &var->ubchginfos[var->nubchginfos-1].bdchgidx : &initbdchgidx);
16263 
16264  if( SCIPbdchgidxIsEarlierNonNull(lbchgidx, ubchgidx) )
16265  return ubchgidx;
16266  else
16267  return lbchgidx;
16268 }
16269 
16270 /** returns the last depth level, at which the bounds of the given variable were tightened;
16271  * returns -2, if the variable's bounds are still the global bounds
16272  * returns -1, if the variable was fixed in presolving
16273  */
16275  SCIP_VAR* var /**< problem variable */
16276  )
16277 {
16278  SCIP_BDCHGIDX* bdchgidx;
16279 
16280  bdchgidx = SCIPvarGetLastBdchgIndex(var);
16281  assert(bdchgidx != NULL);
16282 
16283  return bdchgidx->depth;
16284 }
16285 
16286 /** returns at which depth in the tree a bound change was applied to the variable that conflicts with the
16287  * given bound; returns -1 if the bound does not conflict with the current local bounds of the variable
16288  */
16290  SCIP_VAR* var, /**< problem variable */
16291  SCIP_SET* set, /**< global SCIP settings */
16292  SCIP_BOUNDTYPE boundtype, /**< bound type of the conflicting bound */
16293  SCIP_Real bound /**< conflicting bound */
16294  )
16295 {
16296  int i;
16297 
16298  assert(var != NULL);
16299  assert(set != NULL);
16300  assert(var->scip == set->scip);
16301 
16302  if( boundtype == SCIP_BOUNDTYPE_LOWER )
16303  {
16304  /* check if the bound is in conflict with the current local bounds */
16305  if( SCIPsetIsLE(set, bound, var->locdom.ub) )
16306  return -1;
16307 
16308  /* check if the bound is in conflict with the global bound */
16309  if( SCIPsetIsGT(set, bound, var->glbdom.ub) )
16310  return 0;
16311 
16312  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16313  assert(var->nubchginfos > 0);
16314  assert(SCIPsetIsGT(set, bound, var->ubchginfos[var->nubchginfos-1].newbound));
16315 
16316  /* search for the first conflicting bound change */
16317  for( i = var->nubchginfos-1; i > 0 && SCIPsetIsGT(set, bound, var->ubchginfos[i-1].newbound); --i )
16318  {
16319  assert(var->ubchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16321  }
16322  assert(SCIPsetIsGT(set, bound, var->ubchginfos[i].newbound)); /* bound change i is conflicting */
16323  assert(i == 0 || SCIPsetIsLE(set, bound, var->ubchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16324 
16325  /* return the depth at which the first conflicting bound change took place */
16326  return var->ubchginfos[i].bdchgidx.depth;
16327  }
16328  else
16329  {
16330  assert(boundtype == SCIP_BOUNDTYPE_UPPER);
16331 
16332  /* check if the bound is in conflict with the current local bounds */
16333  if( SCIPsetIsGE(set, bound, var->locdom.lb) )
16334  return -1;
16335 
16336  /* check if the bound is in conflict with the global bound */
16337  if( SCIPsetIsLT(set, bound, var->glbdom.lb) )
16338  return 0;
16339 
16340  /* local bounds are in conflict with the given bound -> there must be at least one conflicting change! */
16341  assert(var->nlbchginfos > 0);
16342  assert(SCIPsetIsLT(set, bound, var->lbchginfos[var->nlbchginfos-1].newbound));
16343 
16344  /* search for the first conflicting bound change */
16345  for( i = var->nlbchginfos-1; i > 0 && SCIPsetIsLT(set, bound, var->lbchginfos[i-1].newbound); --i )
16346  {
16347  assert(var->lbchginfos[i].var == var); /* perform sanity check on the search for the first conflicting bound */
16349  }
16350  assert(SCIPsetIsLT(set, bound, var->lbchginfos[i].newbound)); /* bound change i is conflicting */
16351  assert(i == 0 || SCIPsetIsGE(set, bound, var->lbchginfos[i-1].newbound)); /* bound change i-1 is not conflicting */
16352 
16353  /* return the depth at which the first conflicting bound change took place */
16354  return var->lbchginfos[i].bdchgidx.depth;
16355  }
16356 }
16357 
16358 /** returns whether the first binary variable was fixed earlier than the second one;
16359  * returns FALSE, if the first variable is not fixed, and returns TRUE, if the first variable is fixed, but the
16360  * second one is not fixed
16361  */
16363  SCIP_VAR* var1, /**< first binary variable */
16364  SCIP_VAR* var2 /**< second binary variable */
16365  )
16366 {
16367  SCIP_BDCHGIDX* bdchgidx1;
16368  SCIP_BDCHGIDX* bdchgidx2;
16369 
16370  assert(var1 != NULL);
16371  assert(var2 != NULL);
16372  assert(SCIPvarIsBinary(var1));
16373  assert(SCIPvarIsBinary(var2));
16374 
16375  var1 = SCIPvarGetProbvar(var1);
16376  var2 = SCIPvarGetProbvar(var2);
16377  assert(var1 != NULL);
16378  assert(var2 != NULL);
16379 
16380  /* check, if variables are globally fixed */
16381  if( !SCIPvarIsActive(var2) || var2->glbdom.lb > 0.5 || var2->glbdom.ub < 0.5 )
16382  return FALSE;
16383  if( !SCIPvarIsActive(var1) || var1->glbdom.lb > 0.5 || var1->glbdom.ub < 0.5 )
16384  return TRUE;
16385 
16388  assert(SCIPvarIsBinary(var1));
16389  assert(SCIPvarIsBinary(var2));
16390  assert(var1->nlbchginfos + var1->nubchginfos <= 1);
16391  assert(var2->nlbchginfos + var2->nubchginfos <= 1);
16392  assert(var1->nlbchginfos == 0 || !var1->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16393  assert(var1->nubchginfos == 0 || !var1->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16394  assert(var2->nlbchginfos == 0 || !var2->lbchginfos[0].redundant); /* otherwise, var would be globally fixed */
16395  assert(var2->nubchginfos == 0 || !var2->ubchginfos[0].redundant); /* otherwise, var would be globally fixed */
16396 
16397  if( var1->nlbchginfos == 1 )
16398  bdchgidx1 = &var1->lbchginfos[0].bdchgidx;
16399  else if( var1->nubchginfos == 1 )
16400  bdchgidx1 = &var1->ubchginfos[0].bdchgidx;
16401  else
16402  bdchgidx1 = NULL;
16403 
16404  if( var2->nlbchginfos == 1 )
16405  bdchgidx2 = &var2->lbchginfos[0].bdchgidx;
16406  else if( var2->nubchginfos == 1 )
16407  bdchgidx2 = &var2->ubchginfos[0].bdchgidx;
16408  else
16409  bdchgidx2 = NULL;
16410 
16411  return SCIPbdchgidxIsEarlier(bdchgidx1, bdchgidx2);
16412 }
16413 
16414 
16415 
16416 /*
16417  * Hash functions
16418  */
16419 
16420 /** gets the key (i.e. the name) of the given variable */
16421 SCIP_DECL_HASHGETKEY(SCIPhashGetKeyVar)
16422 { /*lint --e{715}*/
16423  SCIP_VAR* var = (SCIP_VAR*)elem;
16424 
16425  assert(var != NULL);
16426  return var->name;
16427 }
16428 
16429 
16430 
16431 
16432 /*
16433  * simple functions implemented as defines
16434  */
16435 
16436 /* In debug mode, the following methods are implemented as function calls to ensure
16437  * type validity.
16438  * In optimized mode, the methods are implemented as defines to improve performance.
16439  * However, we want to have them in the library anyways, so we have to undef the defines.
16440  */
16441 
16442 #undef SCIPboundchgGetNewbound
16443 #undef SCIPboundchgGetVar
16444 #undef SCIPboundchgGetBoundchgtype
16445 #undef SCIPboundchgGetBoundtype
16446 #undef SCIPboundchgIsRedundant
16447 #undef SCIPdomchgGetNBoundchgs
16448 #undef SCIPdomchgGetBoundchg
16449 #undef SCIPholelistGetLeft
16450 #undef SCIPholelistGetRight
16451 #undef SCIPholelistGetNext
16452 #undef SCIPvarGetName
16453 #undef SCIPvarGetNUses
16454 #undef SCIPvarGetData
16455 #undef SCIPvarSetData
16456 #undef SCIPvarSetDelorigData
16457 #undef SCIPvarSetTransData
16458 #undef SCIPvarSetDeltransData
16459 #undef SCIPvarGetStatus
16460 #undef SCIPvarIsOriginal
16461 #undef SCIPvarIsTransformed
16462 #undef SCIPvarIsNegated
16463 #undef SCIPvarGetType
16464 #undef SCIPvarIsBinary
16465 #undef SCIPvarIsIntegral
16466 #undef SCIPvarIsInitial
16467 #undef SCIPvarIsRemovable
16468 #undef SCIPvarIsDeleted
16469 #undef SCIPvarIsDeletable
16470 #undef SCIPvarMarkDeletable
16471 #undef SCIPvarMarkNotDeletable
16472 #undef SCIPvarIsActive
16473 #undef SCIPvarGetIndex
16474 #undef SCIPvarGetProbindex
16475 #undef SCIPvarGetTransVar
16476 #undef SCIPvarGetCol
16477 #undef SCIPvarIsInLP
16478 #undef SCIPvarGetAggrVar
16479 #undef SCIPvarGetAggrScalar
16480 #undef SCIPvarGetAggrConstant
16481 #undef SCIPvarGetMultaggrNVars
16482 #undef SCIPvarGetMultaggrVars
16483 #undef SCIPvarGetMultaggrScalars
16484 #undef SCIPvarGetMultaggrConstant
16485 #undef SCIPvarGetNegatedVar
16486 #undef SCIPvarGetNegationVar
16487 #undef SCIPvarGetNegationConstant
16488 #undef SCIPvarGetObj
16489 #undef SCIPvarGetLbOriginal
16490 #undef SCIPvarGetUbOriginal
16491 #undef SCIPvarGetHolelistOriginal
16492 #undef SCIPvarGetLbGlobal
16493 #undef SCIPvarGetUbGlobal
16494 #undef SCIPvarGetHolelistGlobal
16495 #undef SCIPvarGetBestBoundGlobal
16496 #undef SCIPvarGetWorstBoundGlobal
16497 #undef SCIPvarGetLbLocal
16498 #undef SCIPvarGetUbLocal
16499 #undef SCIPvarGetHolelistLocal
16500 #undef SCIPvarGetBestBoundLocal
16501 #undef SCIPvarGetWorstBoundLocal
16502 #undef SCIPvarGetBestBoundType
16503 #undef SCIPvarGetWorstBoundType
16504 #undef SCIPvarGetLbLazy
16505 #undef SCIPvarGetUbLazy
16506 #undef SCIPvarGetBranchFactor
16507 #undef SCIPvarGetBranchPriority
16508 #undef SCIPvarGetBranchDirection
16509 #undef SCIPvarGetNVlbs
16510 #undef SCIPvarGetVlbVars
16511 #undef SCIPvarGetVlbCoefs
16512 #undef SCIPvarGetVlbConstants
16513 #undef SCIPvarGetNVubs
16514 #undef SCIPvarGetVubVars
16515 #undef SCIPvarGetVubCoefs
16516 #undef SCIPvarGetVubConstants
16517 #undef SCIPvarGetNImpls
16518 #undef SCIPvarGetImplVars
16519 #undef SCIPvarGetImplTypes
16520 #undef SCIPvarGetImplBounds
16521 #undef SCIPvarGetImplIds
16522 #undef SCIPvarGetNCliques
16523 #undef SCIPvarGetCliques
16524 #undef SCIPvarGetLPSol
16525 #undef SCIPvarGetNLPSol
16526 #undef SCIPvarGetBdchgInfoLb
16527 #undef SCIPvarGetNBdchgInfosLb
16528 #undef SCIPvarGetBdchgInfoUb
16529 #undef SCIPvarGetNBdchgInfosUb
16530 #undef SCIPvarGetValuehistory
16531 #undef SCIPvarGetPseudoSol
16532 #undef SCIPvarCatchEvent
16533 #undef SCIPvarDropEvent
16534 #undef SCIPvarGetVSIDS
16535 #undef SCIPvarGetCliqueComponentIdx
16536 #undef SCIPbdchgidxGetPos
16537 #undef SCIPbdchgidxIsEarlierNonNull
16538 #undef SCIPbdchgidxIsEarlier
16539 #undef SCIPbdchginfoGetOldbound
16540 #undef SCIPbdchginfoGetNewbound
16541 #undef SCIPbdchginfoGetVar
16542 #undef SCIPbdchginfoGetChgtype
16543 #undef SCIPbdchginfoGetBoundtype
16544 #undef SCIPbdchginfoGetDepth
16545 #undef SCIPbdchginfoGetPos
16546 #undef SCIPbdchginfoGetIdx
16547 #undef SCIPbdchginfoGetInferVar
16548 #undef SCIPbdchginfoGetInferCons
16549 #undef SCIPbdchginfoGetInferProp
16550 #undef SCIPbdchginfoGetInferInfo
16551 #undef SCIPbdchginfoGetInferBoundtype
16552 #undef SCIPbdchginfoIsRedundant
16553 #undef SCIPbdchginfoHasInferenceReason
16554 #undef SCIPbdchginfoIsTighter
16555 
16556 
16557 /** returns the new value of the bound in the bound change data */
16559  SCIP_BOUNDCHG* boundchg /**< bound change data */
16560  )
16561 {
16562  assert(boundchg != NULL);
16563 
16564  return boundchg->newbound;
16565 }
16566 
16567 /** returns the variable of the bound change in the bound change data */
16569  SCIP_BOUNDCHG* boundchg /**< bound change data */
16570  )
16571 {
16572  assert(boundchg != NULL);
16573 
16574  return boundchg->var;
16575 }
16576 
16577 /** returns the bound change type of the bound change in the bound change data */
16579  SCIP_BOUNDCHG* boundchg /**< bound change data */
16580  )
16581 {
16582  assert(boundchg != NULL);
16583 
16584  return (SCIP_BOUNDCHGTYPE)(boundchg->boundchgtype);
16585 }
16586 
16587 /** returns the bound type of the bound change in the bound change data */
16589  SCIP_BOUNDCHG* boundchg /**< bound change data */
16590  )
16591 {
16592  assert(boundchg != NULL);
16593 
16594  return (SCIP_BOUNDTYPE)(boundchg->boundtype);
16595 }
16596 
16597 /** returns whether the bound change is redundant due to a more global bound that is at least as strong */
16599  SCIP_BOUNDCHG* boundchg /**< bound change data */
16600  )
16601 {
16602  assert(boundchg != NULL);
16603 
16604  return boundchg->redundant;
16605 }
16606 
16607 /** returns the number of bound changes in the domain change data */
16609  SCIP_DOMCHG* domchg /**< domain change data */
16610  )
16611 {
16612  return domchg != NULL ? domchg->domchgbound.nboundchgs : 0;
16613 }
16614 
16615 /** returns a particular bound change in the domain change data */
16617  SCIP_DOMCHG* domchg, /**< domain change data */
16618  int pos /**< position of the bound change in the domain change data */
16619  )
16620 {
16621  assert(domchg != NULL);
16622  assert(0 <= pos && pos < (int)domchg->domchgbound.nboundchgs);
16623 
16624  return &domchg->domchgbound.boundchgs[pos];
16625 }
16626 
16627 /** returns left bound of open interval in hole */
16629  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16630  )
16631 {
16632  assert(holelist != NULL);
16633 
16634  return holelist->hole.left;
16635 }
16636 
16637 /** returns right bound of open interval in hole */
16639  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16640  )
16641 {
16642  assert(holelist != NULL);
16643 
16644  return holelist->hole.right;
16645 }
16646 
16647 /** returns next hole in list */
16649  SCIP_HOLELIST* holelist /**< hole list pointer to hole of interest */
16650  )
16651 {
16652  assert(holelist != NULL);
16653 
16654  return holelist->next;
16655 }
16656 
16657 /** returns the name of the variable
16658  *
16659  * @note to change the name of a variable, use SCIPchgVarName() from scip.h
16660  */
16661 const char* SCIPvarGetName(
16662  SCIP_VAR* var /**< problem variable */
16663  )
16664 {
16665  assert(var != NULL);
16666 
16667  return var->name;
16668 }
16669 
16670 /** gets number of times, the variable is currently captured */
16671 int SCIPvarGetNUses(
16672  SCIP_VAR* var /**< problem variable */
16673  )
16674 {
16675  assert(var != NULL);
16676 
16677  return var->nuses;
16678 }
16679 
16680 /** returns the user data of the variable */
16682  SCIP_VAR* var /**< problem variable */
16683  )
16684 {
16685  assert(var != NULL);
16686 
16687  return var->vardata;
16688 }
16689 
16690 /** sets the user data for the variable */
16691 void SCIPvarSetData(
16692  SCIP_VAR* var, /**< problem variable */
16693  SCIP_VARDATA* vardata /**< user variable data */
16694  )
16695 {
16696  assert(var != NULL);
16697 
16698  var->vardata = vardata;
16699 }
16700 
16701 /** sets method to free user data for the original variable */
16703  SCIP_VAR* var, /**< problem variable */
16704  SCIP_DECL_VARDELORIG ((*vardelorig)) /**< frees user data of original variable */
16705  )
16706 {
16707  assert(var != NULL);
16708  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16709 
16710  var->vardelorig = vardelorig;
16711 }
16712 
16713 /** sets method to transform user data of the variable */
16714 void SCIPvarSetTransData(
16715  SCIP_VAR* var, /**< problem variable */
16716  SCIP_DECL_VARTRANS ((*vartrans)) /**< creates transformed user data by transforming original user data */
16717  )
16718 {
16719  assert(var != NULL);
16720  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16721 
16722  var->vartrans = vartrans;
16723 }
16724 
16725 /** sets method to free transformed user data for the variable */
16727  SCIP_VAR* var, /**< problem variable */
16728  SCIP_DECL_VARDELTRANS ((*vardeltrans)) /**< frees user data of transformed variable */
16729  )
16730 {
16731  assert(var != NULL);
16732 
16733  var->vardeltrans = vardeltrans;
16734 }
16735 
16736 /** sets method to copy this variable into sub-SCIPs */
16737 void SCIPvarSetCopyData(
16738  SCIP_VAR* var, /**< problem variable */
16739  SCIP_DECL_VARCOPY ((*varcopy)) /**< copy method of the variable */
16740  )
16741 {
16742  assert(var != NULL);
16743 
16744  var->varcopy = varcopy;
16745 }
16746 
16747 /** sets the initial flag of a variable; only possible for original or loose variables */
16749  SCIP_VAR* var, /**< problem variable */
16750  SCIP_Bool initial /**< initial flag */
16751  )
16752 {
16753  assert(var != NULL);
16754 
16756  return SCIP_INVALIDCALL;
16757 
16758  var->initial = initial;
16759 
16760  return SCIP_OKAY;
16761 }
16762 
16763 /** sets the removable flag of a variable; only possible for original or loose variables */
16765  SCIP_VAR* var, /**< problem variable */
16766  SCIP_Bool removable /**< removable flag */
16767  )
16768 {
16769  assert(var != NULL);
16770 
16772  return SCIP_INVALIDCALL;
16773 
16774  var->removable = removable;
16775 
16776  return SCIP_OKAY;
16777 }
16778 
16779 /** gets status of variable */
16781  SCIP_VAR* var /**< problem variable */
16782  )
16783 {
16784  assert(var != NULL);
16785 
16786  return (SCIP_VARSTATUS)(var->varstatus);
16787 }
16788 
16789 /** returns whether the variable belongs to the original problem */
16791  SCIP_VAR* var /**< problem variable */
16792  )
16793 {
16794  assert(var != NULL);
16795  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16796 
16800 }
16801 
16802 /** returns whether the variable belongs to the transformed problem */
16804  SCIP_VAR* var /**< problem variable */
16805  )
16806 {
16807  assert(var != NULL);
16808  assert(SCIPvarGetStatus(var) != SCIP_VARSTATUS_NEGATED || var->negatedvar != NULL);
16809 
16813 }
16814 
16815 /** returns whether the variable was created by negation of a different variable */
16817  SCIP_VAR* var /**< problem variable */
16818  )
16819 {
16820  assert(var != NULL);
16821 
16822  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
16823 }
16824 
16825 /** gets type of variable */
16827  SCIP_VAR* var /**< problem variable */
16828  )
16829 {
16830  assert(var != NULL);
16831 
16832  return (SCIP_VARTYPE)(var->vartype);
16833 }
16834 
16835 /** returns TRUE if the variable is of binary type; this is the case if:
16836  * (1) variable type is binary
16837  * (2) variable type is integer or implicit integer and
16838  * (i) the lazy lower bound or the global lower bound is greater than or equal to zero
16839  * (ii) the lazy upper bound or the global upper bound is less than or equal to one
16840  */
16842  SCIP_VAR* var /**< problem variable */
16843  )
16844 {
16845  assert(var != NULL);
16846 
16847  return (SCIPvarGetType(var) == SCIP_VARTYPE_BINARY ||
16848  (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS && MAX(var->glbdom.lb, var->lazylb) >= 0.0 && MIN(var->glbdom.ub, var->lazyub) <= 1.0));
16849 }
16850 
16851 /** returns whether variable is of integral type (binary, integer, or implicit integer) */
16853  SCIP_VAR* var /**< problem variable */
16854  )
16855 {
16856  assert(var != NULL);
16857 
16858  return (SCIPvarGetType(var) != SCIP_VARTYPE_CONTINUOUS);
16859 }
16860 
16861 /** returns whether variable's column should be present in the initial root LP */
16863  SCIP_VAR* var /**< problem variable */
16864  )
16865 {
16866  assert(var != NULL);
16867 
16868  return var->initial;
16869 }
16870 
16871 /** returns whether variable's column is removable from the LP (due to aging or cleanup) */
16873  SCIP_VAR* var /**< problem variable */
16874  )
16875 {
16876  assert(var != NULL);
16877 
16878  return var->removable;
16879 }
16880 
16881 /** returns whether the variable was deleted from the problem */
16883  SCIP_VAR* var /**< problem variable */
16884  )
16885 {
16886  assert(var != NULL);
16887 
16888  return var->deleted;
16889 }
16890 
16891 /** marks the variable to be deletable, i.e., it may be deleted completely from the problem;
16892  * method can only be called before the variable is added to the problem by SCIPaddVar() or SCIPaddPricedVar()
16893  */
16895  SCIP_VAR* var /**< problem variable */
16896  )
16897 {
16898  assert(var != NULL);
16899  assert(var->probindex == -1);
16900 
16901  var->deletable = TRUE;
16902 }
16903 
16904 /** marks the variable to be not deletable from the problem */
16907  )
16908 {
16909  assert(var != NULL);
16910 
16911  var->deletable = FALSE;
16912 }
16913 
16914 /** marks variable to be deleted from global structures (cliques etc.) when cleaning up
16915  *
16916  * @note: this is not equivalent to marking the variable itself for deletion, this is done by using SCIPvarMarkDeletable()
16917  */
16919  SCIP_VAR* var /**< problem variable */
16920  )
16921 {
16922  assert(var != NULL);
16923 
16924  var->delglobalstructs = TRUE;
16925 }
16926 
16927 /** returns whether the variable was flagged for deletion from global structures (cliques etc.) */
16929  SCIP_VAR* var /**< problem variable */
16930  )
16931 {
16932  assert(var != NULL);
16933 
16934  return var->delglobalstructs;
16935 }
16936 
16937 /** returns whether variable is allowed to be deleted completely from the problem */
16940  )
16941 {
16942  assert(var != NULL);
16943 
16944  return var->deletable;
16945 }
16946 
16947 /** returns whether variable is an active (neither fixed nor aggregated) variable */
16949  SCIP_VAR* var /**< problem variable */
16950  )
16951 {
16952  assert(var != NULL);
16953 
16954  return (var->probindex >= 0);
16955 }
16956 
16957 /** gets unique index of variable */
16958 int SCIPvarGetIndex(
16959  SCIP_VAR* var /**< problem variable */
16960  )
16961 {
16962  assert(var != NULL);
16963 
16964  return var->index;
16965 }
16966 
16967 /** gets position of variable in problem, or -1 if variable is not active */
16969  SCIP_VAR* var /**< problem variable */
16970  )
16971 {
16972  assert(var != NULL);
16973 
16974  return var->probindex;
16975 }
16976 
16977 /** gets transformed variable of ORIGINAL variable */
16979  SCIP_VAR* var /**< problem variable */
16980  )
16981 {
16982  assert(var != NULL);
16983  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_ORIGINAL);
16984 
16985  return var->data.original.transvar;
16986 }
16987 
16988 /** gets column of COLUMN variable */
16990  SCIP_VAR* var /**< problem variable */
16991  )
16992 {
16993  assert(var != NULL);
16994  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN);
16995 
16996  return var->data.col;
16997 }
16998 
16999 /** returns whether the variable is a COLUMN variable that is member of the current LP */
17001  SCIP_VAR* var /**< problem variable */
17002  )
17003 {
17004  assert(var != NULL);
17005 
17006  return (SCIPvarGetStatus(var) == SCIP_VARSTATUS_COLUMN && SCIPcolIsInLP(var->data.col));
17007 }
17008 
17009 /** gets aggregation variable y of an aggregated variable x = a*y + c */
17011  SCIP_VAR* var /**< problem variable */
17012  )
17013 {
17014  assert(var != NULL);
17016 
17017  return var->data.aggregate.var;
17018 }
17019 
17020 /** gets aggregation scalar a of an aggregated variable x = a*y + c */
17022  SCIP_VAR* var /**< problem variable */
17023  )
17024 {
17025  assert(var != NULL);
17027 
17028  return var->data.aggregate.scalar;
17029 }
17030 
17031 /** gets aggregation constant c of an aggregated variable x = a*y + c */
17033  SCIP_VAR* var /**< problem variable */
17034  )
17035 {
17036  assert(var != NULL);
17038 
17039  return var->data.aggregate.constant;
17040 }
17041 
17042 /** gets number n of aggregation variables of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17044  SCIP_VAR* var /**< problem variable */
17045  )
17046 {
17047  assert(var != NULL);
17048  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17049  assert(!var->donotmultaggr);
17050 
17051  return var->data.multaggr.nvars;
17052 }
17053 
17054 /** gets vector of aggregation variables y of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17056  SCIP_VAR* var /**< problem variable */
17057  )
17058 {
17059  assert(var != NULL);
17060  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17061  assert(!var->donotmultaggr);
17062 
17063  return var->data.multaggr.vars;
17064 }
17065 
17066 /** gets vector of aggregation scalars a of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17068  SCIP_VAR* var /**< problem variable */
17069  )
17070 {
17071  assert(var != NULL);
17072  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17073  assert(!var->donotmultaggr);
17074 
17075  return var->data.multaggr.scalars;
17076 }
17077 
17078 /** gets aggregation constant c of a multi aggregated variable x = a0*y0 + ... + a(n-1)*y(n-1) + c */
17080  SCIP_VAR* var /**< problem variable */
17081  )
17082 {
17083  assert(var != NULL);
17084  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_MULTAGGR);
17085  assert(!var->donotmultaggr);
17086 
17087  return var->data.multaggr.constant;
17088 }
17089 
17090 /** gets the negation of the given variable; may return NULL, if no negation is existing yet */
17092  SCIP_VAR* var /**< negated problem variable */
17093  )
17094 {
17095  assert(var != NULL);
17096 
17097  return var->negatedvar;
17098 }
17099 
17100 /** gets the negation variable x of a negated variable x' = offset - x */
17102  SCIP_VAR* var /**< negated problem variable */
17103  )
17104 {
17105  assert(var != NULL);
17106  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17107 
17108  return var->negatedvar;
17109 }
17110 
17111 /** gets the negation offset of a negated variable x' = offset - x */
17113  SCIP_VAR* var /**< negated problem variable */
17114  )
17115 {
17116  assert(var != NULL);
17117  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17118 
17119  return var->data.negate.constant;
17120 }
17121 
17122 /** gets objective function value of variable */
17124  SCIP_VAR* var /**< problem variable */
17125  )
17126 {
17127  assert(var != NULL);
17128 
17129  return var->obj;
17130 }
17131 
17132 /** gets the unchanged objective function value of a variable (ignoring temproray changes performed in probing mode) */
17134  SCIP_VAR* var /**< problem variable */
17135  )
17136 {
17137  assert(var != NULL);
17138 
17139  return var->unchangedobj;
17140 }
17141 
17142 /** gets corresponding objective value of active, fixed, or multi-aggregated problem variable of given variable
17143  * e.g. obj(x) = 1 this method returns for ~x the value -1
17144  */
17146  SCIP_VAR* var, /**< problem variable */
17147  SCIP_Real* aggrobj /**< pointer to store the aggregated objective value */
17148  )
17149 {
17150  SCIP_VAR* probvar = var;
17151  SCIP_Real mult = 1.0;
17152 
17153  assert(probvar != NULL);
17154  assert(aggrobj != NULL);
17155 
17156  while( probvar != NULL )
17157  {
17158  switch( SCIPvarGetStatus(probvar) )
17159  {
17161  case SCIP_VARSTATUS_LOOSE:
17162  case SCIP_VARSTATUS_COLUMN:
17163  (*aggrobj) = mult * SCIPvarGetObj(probvar);
17164  return SCIP_OKAY;
17165 
17166  case SCIP_VARSTATUS_FIXED:
17167  assert(SCIPvarGetObj(probvar) == 0.0);
17168  (*aggrobj) = 0.0;
17169  return SCIP_OKAY;
17170 
17172  /* handle multi-aggregated variables depending on one variable only (possibly caused by SCIPvarFlattenAggregationGraph()) */
17173  if ( probvar->data.multaggr.nvars == 1 )
17174  {
17175  assert( probvar->data.multaggr.vars != NULL );
17176  assert( probvar->data.multaggr.scalars != NULL );
17177  assert( probvar->data.multaggr.vars[0] != NULL );
17178  mult *= probvar->data.multaggr.scalars[0];
17179  probvar = probvar->data.multaggr.vars[0];
17180  break;
17181  }
17182  else
17183  {
17184  SCIP_Real tmpobj;
17185  int v;
17186 
17187  (*aggrobj) = 0.0;
17188 
17189  for( v = probvar->data.multaggr.nvars - 1; v >= 0; --v )
17190  {
17191  SCIP_CALL( SCIPvarGetAggregatedObj(probvar->data.multaggr.vars[v], &tmpobj) );
17192  (*aggrobj) += probvar->data.multaggr.scalars[v] * tmpobj;
17193  }
17194  return SCIP_OKAY;
17195  }
17196 
17197  case SCIP_VARSTATUS_AGGREGATED: /* x = a'*x' + c' => a*x + c == (a*a')*x' + (a*c' + c) */
17198  assert(probvar->data.aggregate.var != NULL);
17199  mult *= probvar->data.aggregate.scalar;
17200  probvar = probvar->data.aggregate.var;
17201  break;
17202 
17203  case SCIP_VARSTATUS_NEGATED: /* x = - x' + c' => a*x + c == (-a)*x' + (a*c' + c) */
17204  assert(probvar->negatedvar != NULL);
17205  assert(SCIPvarGetStatus(probvar->negatedvar) != SCIP_VARSTATUS_NEGATED);
17206  assert(probvar->negatedvar->negatedvar == probvar);
17207  mult *= -1.0;
17208  probvar = probvar->negatedvar;
17209  break;
17210 
17211  default:
17212  SCIPABORT();
17213  return SCIP_INVALIDDATA; /*lint !e527*/
17214  }
17215  }
17216 
17217  return SCIP_INVALIDDATA;
17218 }
17219 
17220 /** gets original lower bound of original problem variable (i.e. the bound set in problem creation) */
17222  SCIP_VAR* var /**< original problem variable */
17223  )
17224 {
17225  assert(var != NULL);
17226  assert(SCIPvarIsOriginal(var));
17227 
17229  return var->data.original.origdom.lb;
17230  else
17231  {
17232  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17233  assert(var->negatedvar != NULL);
17235 
17236  return var->data.negate.constant - var->negatedvar->data.original.origdom.ub;
17237  }
17238 }
17239 
17240 /** gets original upper bound of original problem variable (i.e. the bound set in problem creation) */
17242  SCIP_VAR* var /**< original problem variable */
17243  )
17244 {
17245  assert(var != NULL);
17246  assert(SCIPvarIsOriginal(var));
17247 
17249  return var->data.original.origdom.ub;
17250  else
17251  {
17252  assert(SCIPvarGetStatus(var) == SCIP_VARSTATUS_NEGATED);
17253  assert(var->negatedvar != NULL);
17255 
17256  return var->data.negate.constant - var->negatedvar->data.original.origdom.lb;
17257  }
17258 }
17259 
17260 /** gets the original hole list of an original variable */
17262  SCIP_VAR* var /**< problem variable */
17263  )
17264 {
17265  assert(var != NULL);
17266  assert(SCIPvarIsOriginal(var));
17267 
17269  return var->data.original.origdom.holelist;
17270 
17271  return NULL;
17272 }
17273 
17274 /** gets global lower bound of variable */
17276  SCIP_VAR* var /**< problem variable */
17277  )
17278 {
17279  assert(var != NULL);
17280 
17281  return var->glbdom.lb;
17282 }
17283 
17284 /** gets global upper bound of variable */
17286  SCIP_VAR* var /**< problem variable */
17287  )
17288 {
17289  assert(var != NULL);
17290 
17291  return var->glbdom.ub;
17292 }
17293 
17294 /** gets the global hole list of an active variable */
17296  SCIP_VAR* var /**< problem variable */
17297  )
17298 {
17299  assert(var != NULL);
17300 
17301  return var->glbdom.holelist;
17302 }
17303 
17304 /** gets best global bound of variable with respect to the objective function */
17306  SCIP_VAR* var /**< problem variable */
17307  )
17308 {
17309  assert(var != NULL);
17310 
17311  if( var->obj >= 0.0 )
17312  return var->glbdom.lb;
17313  else
17314  return var->glbdom.ub;
17315 }
17316 
17317 /** gets worst global bound of variable with respect to the objective function */
17319  SCIP_VAR* var /**< problem variable */
17320  )
17321 {
17322  assert(var != NULL);
17323 
17324  if( var->obj >= 0.0 )
17325  return var->glbdom.ub;
17326  else
17327  return var->glbdom.lb;
17328 }
17329 
17330 /** gets current lower bound of variable */
17332  SCIP_VAR* var /**< problem variable */
17333  )
17334 {
17335  assert(var != NULL);
17336 
17337  return var->locdom.lb;
17338 }
17339 
17340 /** gets current upper bound of variable */
17342  SCIP_VAR* var /**< problem variable */
17343  )
17344 {
17345  assert(var != NULL);
17346 
17347  return var->locdom.ub;
17348 }
17349 
17350 /** gets the current hole list of an active variable */
17352  SCIP_VAR* var /**< problem variable */
17353  )
17354 {
17355  assert(var != NULL);
17356 
17357  return var->locdom.holelist;
17358 }
17359 
17360 /** gets best local bound of variable with respect to the objective function */
17362  SCIP_VAR* var /**< problem variable */
17363  )
17364 {
17365  assert(var != NULL);
17366 
17367  if( var->obj >= 0.0 )
17368  return var->locdom.lb;
17369  else
17370  return var->locdom.ub;
17371 }
17372 
17373 /** gets worst local bound of variable with respect to the objective function */
17375  SCIP_VAR* var /**< problem variable */
17376  )
17377 {
17378  assert(var != NULL);
17379 
17380  if( var->obj >= 0.0 )
17381  return var->locdom.ub;
17382  else
17383  return var->locdom.lb;
17384 }
17385 
17386 /** gets type (lower or upper) of best bound of variable with respect to the objective function */
17388  SCIP_VAR* var /**< problem variable */
17389  )
17390 {
17391  assert(var != NULL);
17392 
17393  if( var->obj >= 0.0 )
17394  return SCIP_BOUNDTYPE_LOWER;
17395  else
17396  return SCIP_BOUNDTYPE_UPPER;
17397 }
17398 
17399 /** gets type (lower or upper) of worst bound of variable with respect to the objective function */
17401  SCIP_VAR* var /**< problem variable */
17402  )
17403 {
17404  assert(var != NULL);
17405 
17406  if( var->obj >= 0.0 )
17407  return SCIP_BOUNDTYPE_UPPER;
17408  else
17409  return SCIP_BOUNDTYPE_LOWER;
17410 }
17411 
17412 /** gets lazy lower bound of variable, returns -infinity if the variable has no lazy lower bound */
17414  SCIP_VAR* var /**< problem variable */
17415  )
17416 {
17417  assert(var != NULL);
17418 
17419  return var->lazylb;
17420 }
17421 
17422 /** gets lazy upper bound of variable, returns infinity if the variable has no lazy upper bound */
17424  SCIP_VAR* var /**< problem variable */
17425  )
17426 {
17427  assert(var != NULL);
17428 
17429  return var->lazyub;
17430 }
17431 
17432 /** gets the branch factor of the variable; this value can be used in the branching methods to scale the score
17433  * values of the variables; higher factor leads to a higher probability that this variable is chosen for branching
17434  */
17436  SCIP_VAR* var /**< problem variable */
17437  )
17438 {
17439  assert(var != NULL);
17440 
17441  return var->branchfactor;
17442 }
17443 
17444 /** gets the branch priority of the variable; variables with higher priority should always be preferred to variables
17445  * with lower priority
17446  */
17448  SCIP_VAR* var /**< problem variable */
17449  )
17450 {
17451  assert(var != NULL);
17452 
17453  return var->branchpriority;
17454 }
17455 
17456 /** gets the preferred branch direction of the variable (downwards, upwards, or auto) */
17458  SCIP_VAR* var /**< problem variable */
17459  )
17460 {
17461  assert(var != NULL);
17462 
17463  return (SCIP_BRANCHDIR)var->branchdirection;
17464 }
17465 
17466 /** gets number of variable lower bounds x >= b_i*z_i + d_i of given variable x */
17467 int SCIPvarGetNVlbs(
17468  SCIP_VAR* var /**< problem variable */
17469  )
17470 {
17471  assert(var != NULL);
17472 
17473  return SCIPvboundsGetNVbds(var->vlbs);
17474 }
17475 
17476 /** gets array with bounding variables z_i in variable lower bounds x >= b_i*z_i + d_i of given variable x;
17477  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17478  */
17480  SCIP_VAR* var /**< problem variable */
17481  )
17482 {
17483  assert(var != NULL);
17484 
17485  return SCIPvboundsGetVars(var->vlbs);
17486 }
17487 
17488 /** gets array with bounding coefficients b_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17490  SCIP_VAR* var /**< problem variable */
17491  )
17492 {
17493  assert(var != NULL);
17494 
17495  return SCIPvboundsGetCoefs(var->vlbs);
17496 }
17497 
17498 /** gets array with bounding constants d_i in variable lower bounds x >= b_i*z_i + d_i of given variable x */
17500  SCIP_VAR* var /**< problem variable */
17501  )
17502 {
17503  assert(var != NULL);
17504 
17505  return SCIPvboundsGetConstants(var->vlbs);
17506 }
17507 
17508 /** gets number of variable upper bounds x <= b_i*z_i + d_i of given variable x */
17509 int SCIPvarGetNVubs(
17510  SCIP_VAR* var /**< problem variable */
17511  )
17512 {
17513  assert(var != NULL);
17514 
17515  return SCIPvboundsGetNVbds(var->vubs);
17516 }
17517 
17518 /** gets array with bounding variables z_i in variable upper bounds x <= b_i*z_i + d_i of given variable x;
17519  * the variable bounds are sorted by increasing variable index of the bounding variable z_i (see SCIPvarGetIndex())
17520  */
17522  SCIP_VAR* var /**< problem variable */
17523  )
17524 {
17525  assert(var != NULL);
17526 
17527  return SCIPvboundsGetVars(var->vubs);
17528 }
17529 
17530 /** gets array with bounding coefficients b_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17532  SCIP_VAR* var /**< problem variable */
17533  )
17534 {
17535  assert(var != NULL);
17536 
17537  return SCIPvboundsGetCoefs(var->vubs);
17538 }
17539 
17540 /** gets array with bounding constants d_i in variable upper bounds x <= b_i*z_i + d_i of given variable x */
17542  SCIP_VAR* var /**< problem variable */
17543  )
17544 {
17545  assert(var != NULL);
17546 
17547  return SCIPvboundsGetConstants(var->vubs);
17548 }
17549 
17550 /** gets number of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17551  * there are no implications for nonbinary variable x
17552  */
17553 int SCIPvarGetNImpls(
17554  SCIP_VAR* var, /**< active problem variable */
17555  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17556  )
17557 {
17558  assert(var != NULL);
17559  assert(SCIPvarIsActive(var));
17560 
17561  return SCIPimplicsGetNImpls(var->implics, varfixing);
17562 }
17563 
17564 /** gets array with implication variables y of implications y <= b or y >= b for x == 0 or x == 1 of given active
17565  * problem variable x, there are no implications for nonbinary variable x;
17566  * the implications are sorted such that implications with binary implied variables precede the ones with non-binary
17567  * implied variables, and as a second criteria, the implied variables are sorted by increasing variable index
17568  * (see SCIPvarGetIndex())
17569  */
17571  SCIP_VAR* var, /**< active problem variable */
17572  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17573  )
17574 {
17575  assert(var != NULL);
17576  assert(SCIPvarIsActive(var));
17577 
17578  return SCIPimplicsGetVars(var->implics, varfixing);
17579 }
17580 
17581 /** gets array with implication types of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17582  * variable x (SCIP_BOUNDTYPE_UPPER if y <= b, SCIP_BOUNDTYPE_LOWER if y >= b),
17583  * there are no implications for nonbinary variable x
17584  */
17586  SCIP_VAR* var, /**< active problem variable */
17587  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17588  )
17589 {
17590  assert(var != NULL);
17591  assert(SCIPvarIsActive(var));
17592 
17593  return SCIPimplicsGetTypes(var->implics, varfixing);
17594 }
17595 
17596 /** gets array with implication bounds b of implications y <= b or y >= b for x == 0 or x == 1 of given active problem
17597  * variable x, there are no implications for nonbinary variable x
17598  */
17600  SCIP_VAR* var, /**< active problem variable */
17601  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17602  )
17603 {
17604  assert(var != NULL);
17605  assert(SCIPvarIsActive(var));
17606 
17607  return SCIPimplicsGetBounds(var->implics, varfixing);
17608 }
17609 
17610 /** Gets array with unique ids of implications y <= b or y >= b for x == 0 or x == 1 of given active problem variable x,
17611  * there are no implications for nonbinary variable x.
17612  * If an implication is a shortcut, i.e., it was added as part of the transitive closure of another implication,
17613  * its id is negative, otherwise it is nonnegative.
17614  */
17615 int* SCIPvarGetImplIds(
17616  SCIP_VAR* var, /**< active problem variable */
17617  SCIP_Bool varfixing /**< FALSE for implications for x == 0, TRUE for x == 1 */
17618  )
17619 {
17620  assert(var != NULL);
17621  assert(SCIPvarIsActive(var));
17622 
17623  return SCIPimplicsGetIds(var->implics, varfixing);
17624 }
17625 
17626 /** gets number of cliques, the active variable is contained in */
17627 int SCIPvarGetNCliques(
17628  SCIP_VAR* var, /**< active problem variable */
17629  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17630  )
17631 {
17632  assert(var != NULL);
17633 
17634  return SCIPcliquelistGetNCliques(var->cliquelist, varfixing);
17635 }
17636 
17637 /** gets array of cliques, the active variable is contained in */
17639  SCIP_VAR* var, /**< active problem variable */
17640  SCIP_Bool varfixing /**< FALSE for cliques containing x == 0, TRUE for x == 1 */
17641  )
17642 {
17643  assert(var != NULL);
17644 
17645  return SCIPcliquelistGetCliques(var->cliquelist, varfixing);
17646 }
17647 
17648 /** gets primal LP solution value of variable */
17650  SCIP_VAR* var /**< problem variable */
17651  )
17652 {
17653  assert(var != NULL);
17654 
17656  return SCIPcolGetPrimsol(var->data.col);
17657  else
17658  return SCIPvarGetLPSol_rec(var);
17659 }
17660 
17661 /** gets primal NLP solution value of variable */
17663  SCIP_VAR* var /**< problem variable */
17664  )
17665 {
17666  assert(var != NULL);
17667 
17669  return var->nlpsol;
17670  else
17671  return SCIPvarGetNLPSol_rec(var);
17672 }
17673 
17674 /** return lower bound change info at requested position */
17676  SCIP_VAR* var, /**< problem variable */
17677  int pos /**< requested position */
17678  )
17679 {
17680  assert(pos >= 0);
17681  assert(pos < var->nlbchginfos);
17682 
17683  return &var->lbchginfos[pos];
17684 }
17685 
17686 /** gets the number of lower bound change info array */
17688  SCIP_VAR* var /**< problem variable */
17689  )
17690 {
17691  return var->nlbchginfos;
17692 }
17693 
17694 /** return upper bound change info at requested position */
17696  SCIP_VAR* var, /**< problem variable */
17697  int pos /**< requested position */
17698  )
17699 {
17700  assert(pos >= 0);
17701  assert(pos < var->nubchginfos);
17702 
17703  return &var->ubchginfos[pos];
17704 }
17705 
17706 /** gets the number upper bound change info array */
17708  SCIP_VAR* var /**< problem variable */
17709  )
17710 {
17711  assert(var != NULL);
17712 
17713  return var->nubchginfos;
17714 }
17715 
17716 /** returns the value based history for the variable */
17718  SCIP_VAR* var /**< problem variable */
17719  )
17720 {
17721  assert(var != NULL);
17722 
17723  return var->valuehistory;
17724 }
17725 
17726 /** gets pseudo solution value of variable */
17728  SCIP_VAR* var /**< problem variable */
17729  )
17730 {
17731  assert(var != NULL);
17732 
17734  return SCIPvarGetBestBoundLocal(var);
17735  else
17736  return SCIPvarGetPseudoSol_rec(var);
17737 }
17738 
17739 /** returns the variable's VSIDS score */
17741  SCIP_VAR* var, /**< problem variable */
17742  SCIP_STAT* stat, /**< problem statistics */
17743  SCIP_BRANCHDIR dir /**< branching direction (downwards, or upwards) */
17744  )
17745 {
17746  assert(var != NULL);
17747 
17749  return SCIPhistoryGetVSIDS(var->history, dir)/stat->vsidsweight;
17750  else
17751  return SCIPvarGetVSIDS_rec(var, stat, dir);
17752 }
17753 
17754 /** includes event handler with given data in variable's event filter */
17756  SCIP_VAR* var, /**< problem variable */
17757  BMS_BLKMEM* blkmem, /**< block memory */
17758  SCIP_SET* set, /**< global SCIP settings */
17759  SCIP_EVENTTYPE eventtype, /**< event type to catch */
17760  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17761  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17762  int* filterpos /**< pointer to store position of event filter entry, or NULL */
17763  )
17764 {
17765  assert(var != NULL);
17766  assert(set != NULL);
17767  assert(var->scip == set->scip);
17768  assert(var->eventfilter != NULL);
17769  assert((eventtype & ~SCIP_EVENTTYPE_VARCHANGED) == 0);
17770  assert((eventtype & SCIP_EVENTTYPE_VARCHANGED) != 0);
17771  assert(SCIPvarIsTransformed(var));
17772 
17773  SCIPsetDebugMsg(set, "catch event of type 0x%" SCIP_EVENTTYPE_FORMAT " of variable <%s> with handler %p and data %p\n",
17774  eventtype, var->name, (void*)eventhdlr, (void*)eventdata);
17775 
17776  SCIP_CALL( SCIPeventfilterAdd(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17777 
17778  return SCIP_OKAY;
17779 }
17780 
17781 /** deletes event handler with given data from variable's event filter */
17783  SCIP_VAR* var, /**< problem variable */
17784  BMS_BLKMEM* blkmem, /**< block memory */
17785  SCIP_SET* set, /**< global SCIP settings */
17786  SCIP_EVENTTYPE eventtype, /**< event type mask of dropped event */
17787  SCIP_EVENTHDLR* eventhdlr, /**< event handler to call for the event processing */
17788  SCIP_EVENTDATA* eventdata, /**< event data to pass to the event handler for the event processing */
17789  int filterpos /**< position of event filter entry returned by SCIPvarCatchEvent(), or -1 */
17790  )
17791 {
17792  assert(var != NULL);
17793  assert(set != NULL);
17794  assert(var->scip == set->scip);
17795  assert(var->eventfilter != NULL);
17796  assert(SCIPvarIsTransformed(var));
17797 
17798  SCIPsetDebugMsg(set, "drop event of variable <%s> with handler %p and data %p\n", var->name, (void*)eventhdlr,
17799  (void*)eventdata);
17800 
17801  SCIP_CALL( SCIPeventfilterDel(var->eventfilter, blkmem, set, eventtype, eventhdlr, eventdata, filterpos) );
17802 
17803  return SCIP_OKAY;
17804 }
17805 
17806 /** returns the position of the bound change index */
17807 int SCIPbdchgidxGetPos(
17808  SCIP_BDCHGIDX* bdchgidx /**< bound change index */
17809  )
17810 {
17811  assert(bdchgidx != NULL);
17812 
17813  return bdchgidx->pos;
17814 }
17815 
17816 /** returns whether first bound change index belongs to an earlier applied bound change than second one */
17818  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index */
17819  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index */
17820  )
17821 {
17822  assert(bdchgidx1 != NULL);
17823  assert(bdchgidx1->depth >= -2);
17824  assert(bdchgidx1->pos >= 0);
17825  assert(bdchgidx2 != NULL);
17826  assert(bdchgidx2->depth >= -2);
17827  assert(bdchgidx2->pos >= 0);
17828 
17829  return (bdchgidx1->depth < bdchgidx2->depth)
17830  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17831 }
17832 
17833 /** returns whether first bound change index belongs to an earlier applied bound change than second one;
17834  * if a bound change index is NULL, the bound change index represents the current time, i.e. the time after the
17835  * last bound change was applied to the current node
17836  */
17838  SCIP_BDCHGIDX* bdchgidx1, /**< first bound change index, or NULL */
17839  SCIP_BDCHGIDX* bdchgidx2 /**< second bound change index, or NULL */
17840  )
17841 {
17842  assert(bdchgidx1 == NULL || bdchgidx1->depth >= -2);
17843  assert(bdchgidx1 == NULL || bdchgidx1->pos >= 0);
17844  assert(bdchgidx2 == NULL || bdchgidx2->depth >= -2);
17845  assert(bdchgidx2 == NULL || bdchgidx2->pos >= 0);
17846 
17847  if( bdchgidx1 == NULL )
17848  return FALSE;
17849  else if( bdchgidx2 == NULL )
17850  return TRUE;
17851  else
17852  return (bdchgidx1->depth < bdchgidx2->depth)
17853  || (bdchgidx1->depth == bdchgidx2->depth && (bdchgidx1->pos < bdchgidx2->pos));
17854 }
17855 
17856 /** returns old bound that was overwritten for given bound change information */
17858  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17859  )
17860 {
17861  assert(bdchginfo != NULL);
17862 
17863  return bdchginfo->oldbound;
17864 }
17865 
17866 /** returns new bound installed for given bound change information */
17868  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17869  )
17870 {
17871  assert(bdchginfo != NULL);
17872 
17873  return bdchginfo->newbound;
17874 }
17875 
17876 /** returns variable that belongs to the given bound change information */
17878  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17879  )
17880 {
17881  assert(bdchginfo != NULL);
17882 
17883  return bdchginfo->var;
17884 }
17885 
17886 /** returns whether the bound change information belongs to a branching decision or a deduction */
17888  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17889  )
17890 {
17891  assert(bdchginfo != NULL);
17892 
17893  return (SCIP_BOUNDCHGTYPE)(bdchginfo->boundchgtype);
17894 }
17895 
17896 /** returns whether the bound change information belongs to a lower or upper bound change */
17898  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17899  )
17900 {
17901  assert(bdchginfo != NULL);
17902 
17903  return (SCIP_BOUNDTYPE)(bdchginfo->boundtype);
17904 }
17905 
17906 /** returns depth level of given bound change information */
17908  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17909  )
17910 {
17911  assert(bdchginfo != NULL);
17912 
17913  return bdchginfo->bdchgidx.depth;
17914 }
17915 
17916 /** returns bound change position in its depth level of given bound change information */
17918  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17919  )
17920 {
17921  assert(bdchginfo != NULL);
17922 
17923  return bdchginfo->bdchgidx.pos;
17924 }
17925 
17926 /** returns bound change index of given bound change information */
17928  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17929  )
17930 {
17931  assert(bdchginfo != NULL);
17932 
17933  return &bdchginfo->bdchgidx;
17934 }
17935 
17936 /** returns inference variable of given bound change information */
17938  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17939  )
17940 {
17941  assert(bdchginfo != NULL);
17944 
17945  return bdchginfo->inferencedata.var;
17946 }
17947 
17948 /** returns inference constraint of given bound change information */
17950  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17951  )
17952 {
17953  assert(bdchginfo != NULL);
17955  assert(bdchginfo->inferencedata.reason.cons != NULL);
17956 
17957  return bdchginfo->inferencedata.reason.cons;
17958 }
17959 
17960 /** returns inference propagator of given bound change information, or NULL if no propagator was responsible */
17962  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17963  )
17964 {
17965  assert(bdchginfo != NULL);
17967 
17968  return bdchginfo->inferencedata.reason.prop;
17969 }
17970 
17971 /** returns inference user information of given bound change information */
17973  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17974  )
17975 {
17976  assert(bdchginfo != NULL);
17979 
17980  return bdchginfo->inferencedata.info;
17981 }
17982 
17983 /** returns inference bound of inference variable of given bound change information */
17985  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
17986  )
17987 {
17988  assert(bdchginfo != NULL);
17991 
17992  return (SCIP_BOUNDTYPE)(bdchginfo->inferboundtype);
17993 }
17994 
17995 /** returns the relaxed bound change type */
17997  SCIP_BDCHGINFO* bdchginfo /**< bound change to add to the conflict set */
17998  )
17999 {
18000  return ((SCIP_BOUNDTYPE)(bdchginfo->boundtype) == SCIP_BOUNDTYPE_LOWER ? bdchginfo->var->conflictrelaxedlb : bdchginfo->var->conflictrelaxedub);
18001 }
18002 
18003 
18004 /** returns whether the bound change information belongs to a redundant bound change */
18006  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18007  )
18008 {
18009  assert(bdchginfo != NULL);
18010  assert(bdchginfo->redundant == (bdchginfo->oldbound == bdchginfo->newbound)); /*lint !e777*/
18011 
18012  return bdchginfo->redundant;
18013 }
18014 
18015 /** returns whether the bound change has an inference reason (constraint or propagator), that can be resolved */
18017  SCIP_BDCHGINFO* bdchginfo /**< bound change information */
18018  )
18019 {
18020  assert(bdchginfo != NULL);
18021 
18024  && bdchginfo->inferencedata.reason.prop != NULL);
18025 }
18026 
18027 /** for two bound change informations belonging to the same variable and bound, returns whether the first bound change
18028  * has a tighter new bound as the second bound change
18029  */
18031  SCIP_BDCHGINFO* bdchginfo1, /**< first bound change information */
18032  SCIP_BDCHGINFO* bdchginfo2 /**< second bound change information */
18033  )
18034 {
18035  assert(bdchginfo1 != NULL);
18036  assert(bdchginfo2 != NULL);
18037  assert(bdchginfo1->var == bdchginfo2->var);
18038  assert(bdchginfo1->boundtype == bdchginfo2->boundtype);
18039 
18040  return (SCIPbdchginfoGetBoundtype(bdchginfo1) == SCIP_BOUNDTYPE_LOWER
18041  ? bdchginfo1->newbound > bdchginfo2->newbound
18042  : bdchginfo1->newbound < bdchginfo2->newbound);
18043 }
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:163
enum SCIP_BoundType SCIP_BOUNDTYPE
Definition: type_lp.h:50
SCIP_RETCODE SCIPeventfilterCreate(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem)
Definition: event.c:1698
SCIP_Real SCIPbdchginfoGetRelaxedBound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17997
void SCIPcliquelistRemoveFromCliques(SCIP_CLIQUELIST *cliquelist, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool irrelevantvar)
Definition: implics.c:1661
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:14810
SCIP_Real SCIPvarGetWorstBoundLocal(SCIP_VAR *var)
Definition: var.c:17375
SCIP_Bool SCIPsetIsInfinity(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5776
SCIP_Real * SCIPvarGetVlbCoefs(SCIP_VAR *var)
Definition: var.c:17490
#define BMSfreeBlockMemoryArrayNull(mem, ptr, num)
Definition: memory.h:449
void SCIPvarGetClosestVlb(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvlb, int *closestvlbidx)
Definition: var.c:13528
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:17401
static void checkImplic(SCIP_SET *set, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype, SCIP_Real implbound, SCIP_Bool *redundant, SCIP_Bool *infeasible)
Definition: var.c:9015
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:14937
SCIP_Bool SCIPvarsHaveCommonClique(SCIP_VAR *var1, SCIP_Bool value1, SCIP_VAR *var2, SCIP_Bool value2, SCIP_Bool regardimplics)
Definition: var.c:10889
SCIP_BRANCHINGDATA branchingdata
Definition: struct_var.h:87
void SCIPhistoryIncNBranchings(SCIP_HISTORY *history, SCIP_BRANCHDIR dir, int depth)
Definition: history.c:568
SCIP_VAR ** SCIPcliqueGetVars(SCIP_CLIQUE *clique)
Definition: implics.c:3353
SCIP_Bool SCIPsetIsLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5834
SCIP_Bool SCIPsetIsFeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6284
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:14457
static SCIP_RETCODE varEventImplAdded(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue)
Definition: var.c:8897
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:10006
SCIP_Real SCIPvarGetBdAtIndex(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16195
SCIP_PROP * SCIPbdchginfoGetInferProp(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17962
void SCIPvarMarkNotDeletable(SCIP_VAR *var)
Definition: var.c:16906
void SCIPvarUpdateBestRootSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:12688
SCIP_RETCODE SCIPvarSetNLPSol(SCIP_VAR *var, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:13412
public methods for branching and inference history structure
SCIP_Bool SCIPlpDiving(SCIP_LP *lp)
Definition: lp.c:16992
int nubchginfos
Definition: struct_var.h:263
SCIP_RETCODE SCIPvarAddObj(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_PROB *transprob, SCIP_PROB *origprob, SCIP_PRIMAL *primal, SCIP_TREE *tree, SCIP_REOPT *reopt, SCIP_LP *lp, SCIP_EVENTQUEUE *eventqueue, SCIP_Real addobj)
Definition: var.c:5976
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoLb(SCIP_VAR *var, int pos)
Definition: var.c:17676
SCIP_Real * SCIPvarGetMultaggrScalars(SCIP_VAR *var)
Definition: var.c:17068
union SCIP_BoundChg::@12 data
internal methods for branch and bound tree
SCIP_Longint SCIPgetNLPIterations(SCIP *scip)
Definition: scip.c:42333
SCIP_BDCHGIDX bdchgidx
Definition: struct_var.h:112
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:15716
SCIP_RETCODE SCIPvaluehistoryCreate(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:228
SCIP_Real SCIPsetFeastol(SCIP_SET *set)
Definition: set.c:5678
SCIP_Real SCIPvarGetBranchFactor(SCIP_VAR *var)
Definition: var.c:17436
unsigned int inferboundtype
Definition: struct_var.h:93
SCIP_Real SCIPbdchginfoGetOldbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17858
char * name
Definition: struct_var.h:229
static SCIP_RETCODE domchgCreate(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:962
unsigned int boundchgtype
Definition: struct_var.h:114
SCIP_BRANCHDIR SCIPvarGetBranchDirection(SCIP_VAR *var)
Definition: var.c:17458
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:1129
SCIP_HOLE hole
Definition: struct_var.h:51
SCIP_Real bestrootsol
Definition: struct_var.h:207
char * name
Definition: struct_lp.h:217
SCIP_Real SCIPvarGetUbLazy(SCIP_VAR *var)
Definition: var.c:17424
SCIP_Real SCIPsetFloor(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5963
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:6470
SCIP_Bool SCIPsetIsFeasEQ(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6174
int SCIPvarGetNVlbs(SCIP_VAR *var)
Definition: var.c:17468
SCIP_VAR * SCIPbdchginfoGetVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17878
#define SCIPsetDuplicateBufferArray(set, ptr, source, num)
Definition: set.h:1879
SCIP_Real SCIPvarGetWorstBoundGlobal(SCIP_VAR *var)
Definition: var.c:17319
#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:6820
enum SCIP_BaseStat SCIP_BASESTAT
Definition: type_lpi.h:86
SCIP_Bool SCIPvarDoNotMultaggr(SCIP_VAR *var)
Definition: var.c:5592
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:2035
SCIP_Real SCIPvarGetPseudocostCountCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14022
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:4516
int SCIPvarGetLastBdchgDepth(SCIP_VAR *var)
Definition: var.c:16275
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:2117
SCIP_Real SCIPvarGetLbGlobal(SCIP_VAR *var)
Definition: var.c:17276
SCIP_Real SCIPvarGetAvgBranchdepth(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15193
SCIP_RETCODE SCIPvarGetProbvarBinary(SCIP_VAR **var, SCIP_Bool *negated)
Definition: var.c:11720
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:14189
#define SCIP_MAXSTRLEN
Definition: def.h:259
SCIP_DOM origdom
Definition: struct_var.h:169
SCIP_BASESTAT SCIPcolGetBasisStatus(SCIP_COL *col)
Definition: lp.c:16243
SCIP_Bool SCIPvarIsInitial(SCIP_VAR *var)
Definition: var.c:16863
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:3304
SCIP_RETCODE SCIPvarChgLbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6202
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:125
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:5899
SCIP_Real lastbranchvalue
Definition: struct_stat.h:129
static SCIP_RETCODE domchgMakeDynamic(SCIP_DOMCHG **domchg, BMS_BLKMEM *blkmem)
Definition: var.c:1032
SCIP_VAR ** SCIPvarGetMultaggrVars(SCIP_VAR *var)
Definition: var.c:17056
static long bound
#define SCIPdebugCheckImplic(set, var, varfixing, implvar, impltype, implbound)
Definition: debug.h:256
#define MAXABSVBCOEF
Definition: var.c:66
#define SCIPsetAllocCleanBufferArray(set, ptr, num)
Definition: set.h:1888
static SCIP_Real getImplVarRedcost(SCIP_VAR *var, SCIP_SET *set, SCIP_Bool varfixing, SCIP_STAT *stat, SCIP_LP *lp)
Definition: var.c:12822
SCIP_RETCODE SCIPbdchginfoCreate(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem, SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_Real oldbound, SCIP_Real newbound)
Definition: var.c:15770
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:1856
SCIP_Real SCIPvarGetLbLocal(SCIP_VAR *var)
Definition: var.c:17332
SCIP_RETCODE SCIPvarChgLbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazylb)
Definition: var.c:7104
SCIP_Real constant
Definition: struct_var.h:184
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:17639
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:208
SCIP_Real SCIPvarGetMultaggrLbGlobal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8199
SCIP_HISTORY * historycrun
Definition: struct_var.h:245
SCIP_BRANCHDIR lastbranchdir
Definition: struct_stat.h:168
SCIP_VALUEHISTORY * SCIPvarGetValuehistory(SCIP_VAR *var)
Definition: var.c:17718
int SCIPcliquelistGetNCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3419
SCIP_NODE * SCIPnodeGetParent(SCIP_NODE *node)
Definition: tree.c:7622
void SCIPprobAddObjoffset(SCIP_PROB *prob, SCIP_Real addval)
Definition: prob.c:1420
void SCIPvarSetTransData(SCIP_VAR *var, SCIP_DECL_VARTRANS((*vartrans)))
Definition: var.c:16715
SCIP_RETCODE SCIPvarChgUbOriginal(SCIP_VAR *var, SCIP_SET *set, SCIP_Real newbound)
Definition: var.c:6261
SCIP_Longint closestvblpcount
Definition: struct_var.h:247
SCIP_RETCODE SCIPvarAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8507
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:16842
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:6397
SCIP_VAR ** SCIPvboundsGetVars(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3271
SCIP_Real SCIPsetInfinity(SCIP_SET *set)
Definition: set.c:5636
SCIP_DOMCHGBOTH domchgboth
Definition: struct_var.h:154
SCIP_RETCODE SCIPcolChgObj(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: lp.c:3601
SCIP_Real SCIPvarGetSol(SCIP_VAR *var, SCIP_Bool getlpval)
Definition: var.c:12665
int SCIPprobGetNVars(SCIP_PROB *prob)
Definition: prob.c:2305
SCIP_BDCHGINFO * ubchginfos
Definition: struct_var.h:243
SCIP_Bool SCIPbdchgidxIsEarlier(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17838
SCIP_Bool SCIPvarWasFixedAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16215
SCIP_Real SCIPvarGetBestBoundLocal(SCIP_VAR *var)
Definition: var.c:17362
SCIP_Real SCIPvarGetRootSol(SCIP_VAR *var)
Definition: var.c:12758
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:5815
SCIP_RETCODE SCIPvarScaleVSIDS(SCIP_VAR *var, SCIP_Real scalar)
Definition: var.c:14543
SCIP_Real SCIPvarGetLbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12342
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:16589
unsigned int nboundchgs
Definition: struct_var.h:123
SCIP_RETCODE SCIPvarCatchEvent(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTTYPE eventtype, SCIP_EVENTHDLR *eventhdlr, SCIP_EVENTDATA *eventdata, int *filterpos)
Definition: var.c:17756
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:3182
SCIP_HOLELIST * newlist
Definition: struct_var.h:59
SCIP_Real right
Definition: struct_var.h:45
void SCIPvaluehistoryScaleVSIDS(SCIP_VALUEHISTORY *valuehistory, SCIP_Real scalar)
Definition: history.c:314
void SCIPvarSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5735
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:4326
SCIP_HOLELIST * SCIPholelistGetNext(SCIP_HOLELIST *holelist)
Definition: var.c:16649
#define FALSE
Definition: def.h:64
int lppos
Definition: struct_lp.h:163
#define EPSEQ(x, y, eps)
Definition: def.h:174
#define EPSISINT(x, eps)
Definition: def.h:186
SCIP_Bool SCIPlpIsSolBasic(SCIP_LP *lp)
Definition: lp.c:16982
SCIP_Bool SCIPsetIsFeasIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6317
int SCIPvarGetNBdchgInfosLb(SCIP_VAR *var)
Definition: var.c:17688
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:16185
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:16165
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:194
int SCIPsnprintf(char *t, int len, const char *s,...)
Definition: misc.c:10011
SCIP_Bool SCIPsetIsZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5888
SCIP_RETCODE SCIPvboundsDel(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, SCIP_VAR *vbdvar, SCIP_Bool negativecoef)
Definition: implics.c:283
static SCIP_Bool useValuehistory(SCIP_VAR *var, SCIP_Real value, SCIP_SET *set)
Definition: var.c:14429
#define TRUE
Definition: def.h:63
SCIP_Bool SCIPvarHasImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_BOUNDTYPE impltype)
Definition: var.c:10560
static void varSetProbindex(SCIP_VAR *var, int probindex)
Definition: var.c:5716
SCIP_Real SCIPvarGetAvgConflictlength(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:14766
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:111
enum SCIP_Retcode SCIP_RETCODE
Definition: type_retcode.h:53
SCIP_HOLELIST * oldlist
Definition: struct_var.h:60
SCIP_Real SCIPvarGetNegationConstant(SCIP_VAR *var)
Definition: var.c:17113
#define MAXIMPLSCLOSURE
Definition: var.c:63
int SCIPvarGetNVubs(SCIP_VAR *var)
Definition: var.c:17510
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:17973
int nlbchginfos
Definition: struct_var.h:261
static SCIP_BDCHGIDX presolvebdchgidx
Definition: var.c:16235
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:1877
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:1992
int SCIPvarGetProbindex(SCIP_VAR *var)
Definition: var.c:16969
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:10361
#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:7882
void SCIPvarSetNamePointer(SCIP_VAR *var, const char *name)
Definition: var.c:5750
int SCIPsetCalcMemGrowSize(SCIP_SET *set, int num)
Definition: set.c:5326
#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:7856
SCIP_Real SCIPvarGetAggrScalar(SCIP_VAR *var)
Definition: var.c:17022
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:6963
static GRAPHNODE ** active
SCIP_Real SCIPvarGetInferenceSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15383
void SCIPvarMarkDeletable(SCIP_VAR *var)
Definition: var.c:16895
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:831
SCIP_Real SCIPvarGetAvgInferences(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15471
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:10684
SCIP_VAR ** SCIPvarGetVlbVars(SCIP_VAR *var)
Definition: var.c:17480
void SCIPprobUpdateNObjVars(SCIP_PROB *prob, SCIP_SET *set, SCIP_Real oldobj, SCIP_Real newobj)
Definition: prob.c:1530
SCIP_RETCODE SCIPvarsGetActiveVars(SCIP_SET *set, SCIP_VAR **vars, int *nvars, int varssize, int *requiredsize)
Definition: var.c:11417
int SCIPbdchgidxGetPos(SCIP_BDCHGIDX *bdchgidx)
Definition: var.c:17808
SCIP_CLIQUE ** SCIPcliquelistGetCliques(SCIP_CLIQUELIST *cliquelist, SCIP_Bool value)
Definition: implics.c:3428
int index
Definition: struct_var.h:248
SCIP_Real constant
Definition: struct_var.h:177
unsigned int domchgtype
Definition: struct_var.h:142
SCIP_Bool SCIPsetIsNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5910
SCIP_RETCODE SCIPcliquelistAdd(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1460
SCIP_Bool SCIPvarIsDeletable(SCIP_VAR *var)
Definition: var.c:16939
int SCIPvarGetConflictingBdchgDepth(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real bound)
Definition: var.c:16290
SCIP_RETCODE SCIPvarUpdatePseudocost(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real solvaldelta, SCIP_Real objdelta, SCIP_Real weight)
Definition: var.c:13783
#define SCIPsetFreeBufferArray(set, ptr)
Definition: set.h:1884
SCIP_Longint SCIPvarGetNBranchingsCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15150
SCIP_Bool SCIPvarIsRemovable(SCIP_VAR *var)
Definition: var.c:16873
void SCIPvarAdjustLb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *lb)
Definition: var.c:6152
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:255
SCIP_RETCODE SCIPvarChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11230
SCIP_Real SCIPhistoryGetAvgCutoffs(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:668
SCIP_HOLECHG * holechgs
Definition: struct_var.h:134
SCIP_Real obj
Definition: struct_var.h:203
SCIP_VAR * SCIPvarGetNegationVar(SCIP_VAR *var)
Definition: var.c:17102
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:5403
SCIP_Real relaxsol
Definition: struct_var.h:210
SCIP_RETCODE SCIPvarRemoveCliquesImplicsVbs(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool irrelevantvar, SCIP_Bool onlyredundant, SCIP_Bool removefromvar)
Definition: var.c:1532
static SCIP_RETCODE boundchgCaptureData(SCIP_BOUNDCHG *boundchg)
Definition: var.c:892
SCIP_Real SCIPsetCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5974
int conflictlbcount
Definition: struct_var.h:264
SCIP_Real SCIPvarGetRelaxSolTransVar(SCIP_VAR *var)
Definition: var.c:13401
#define SCIPstatIncrement(stat, set, field)
Definition: stat.h:251
SCIP_Real SCIPsetGetHugeValue(SCIP_SET *set)
Definition: set.c:5648
internal methods for LP management
SCIP_BDCHGIDX * SCIPvarGetLastBdchgIndex(SCIP_VAR *var)
Definition: var.c:16238
int SCIPvarGetNCliques(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17628
SCIP_Real SCIPvarGetLPSol_rec(SCIP_VAR *var)
Definition: var.c:12479
SCIP_Real SCIPhistoryGetPseudocost(SCIP_HISTORY *history, SCIP_Real solvaldelta)
Definition: history.c:423
SCIP_VAR ** vars
Definition: struct_var.h:186
static void domMerge(SCIP_DOM *dom, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real *newlb, SCIP_Real *newub)
Definition: var.c:190
real eps
internal methods for branching and inference history
int nrootintfixings
Definition: struct_stat.h:204
int branchpriority
Definition: struct_var.h:259
SCIP_Real SCIPvarGetCutoffSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15626
int * SCIPvarGetImplIds(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17616
SCIP_HOLELIST * SCIPvarGetHolelistOriginal(SCIP_VAR *var)
Definition: var.c:17262
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:1298
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:201
SCIP_DECL_HASHKEYVAL(SCIPvarGetHashkeyVal)
Definition: var.c:11410
SCIP_VAR * var
Definition: struct_var.h:178
#define SCIP_EVENTTYPE_LBCHANGED
Definition: type_event.h:104
SCIP_Real SCIPvarGetUbLP(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:12412
int nrootboundchgs
Definition: struct_stat.h:202
#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:5870
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:7181
SCIP_HISTORY * glbhistorycrun
Definition: struct_stat.h:163
internal methods for propagators
SCIP_VAR * SCIPvarGetNegatedVar(SCIP_VAR *var)
Definition: var.c:17092
const char * SCIPgetProbName(SCIP *scip)
Definition: scip.c:10891
SCIP_Bool SCIPhashmapExists(SCIP_HASHMAP *hashmap, void *origin)
Definition: misc.c:3025
SCIP_Real SCIPvarGetVSIDSCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15332
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:8721
SCIP_Real SCIPvarGetNLPSol_rec(SCIP_VAR *var)
Definition: var.c:12551
int SCIPvarGetNBdchgInfosUb(SCIP_VAR *var)
Definition: var.c:17708
void SCIPcliquelistFree(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem)
Definition: implics.c:1419
SCIP_Real conflictrelaxedub
Definition: struct_var.h:216
SCIP_Longint SCIPnodeGetNumber(SCIP_NODE *node)
Definition: tree.c:7342
SCIP_Bool SCIPbdchginfoIsTighter(SCIP_BDCHGINFO *bdchginfo1, SCIP_BDCHGINFO *bdchginfo2)
Definition: var.c:18031
unsigned int inferboundtype
Definition: struct_var.h:116
SCIP_RETCODE SCIPeventCreateVarFixed(SCIP_EVENT **event, BMS_BLKMEM *blkmem, SCIP_VAR *var)
Definition: event.c:514
union SCIP_Var::@13 data
SCIP_RETCODE SCIPvarChgLbLocal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_LP *lp, SCIP_BRANCHCAND *branchcand, SCIP_EVENTQUEUE *eventqueue, SCIP_Real newbound)
Definition: var.c:7605
SCIP_Real SCIPvarGetUbGlobal(SCIP_VAR *var)
Definition: var.c:17286
SCIP_Bool SCIPsetIsLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5816
SCIP_VAR * SCIPvarGetProbvar(SCIP_VAR *var)
Definition: var.c:11628
SCIP_Real SCIPvarGetObjLP(SCIP_VAR *var)
Definition: var.c:12296
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:5850
SCIP_Real SCIPvarGetBestRootLPObjval(SCIP_VAR *var)
Definition: var.c:13222
void SCIPvarSetHistory(SCIP_VAR *var, SCIP_HISTORY *history, SCIP_STAT *stat)
Definition: var.c:4311
static SCIP_RETCODE varProcessChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10910
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:12875
SCIP_RETCODE SCIPstatUpdateVarRootLPBestEstimate(SCIP_STAT *stat, SCIP_SET *set, SCIP_VAR *var, SCIP_Real oldrootpscostscore)
Definition: stat.c:700
void SCIPvaluehistoryFree(SCIP_VALUEHISTORY **valuehistory, BMS_BLKMEM *blkmem)
Definition: history.c:247
SCIP_Real conflictrelaxedlb
Definition: struct_var.h:215
void SCIPvarSetDelorigData(SCIP_VAR *var, SCIP_DECL_VARDELORIG((*vardelorig)))
Definition: var.c:16703
enum SCIP_Confidencelevel SCIP_CONFIDENCELEVEL
Definition: type_misc.h:44
SCIP_RETCODE SCIPvarChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11100
SCIP_Real SCIPvarGetPseudocost(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13881
SCIP_AGGREGATE aggregate
Definition: struct_var.h:225
SCIP_Real lazylb
Definition: struct_var.h:217
#define BMSduplicateBlockMemoryArray(mem, ptr, source, num)
Definition: memory.h:443
SCIP_Real SCIPcolGetPrimsol(SCIP_COL *col)
Definition: lp.c:16208
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:7219
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:1763
void SCIPvarSetDeltransData(SCIP_VAR *var, SCIP_DECL_VARDELTRANS((*vardeltrans)))
Definition: var.c:16727
SCIP_RETCODE SCIPvarChgUbLazy(SCIP_VAR *var, SCIP_SET *set, SCIP_Real lazyub)
Definition: var.c:7127
SCIP_Real SCIPvarGetBestBoundGlobal(SCIP_VAR *var)
Definition: var.c:17306
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:7439
void SCIPvarMergeHistories(SCIP_VAR *targetvar, SCIP_VAR *othervar, SCIP_STAT *stat)
Definition: var.c:4295
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:3313
internal methods for storing and manipulating the main problem
#define MAX_CLIQUELENGTH
Definition: var.c:12871
#define SCIPerrorMessage
Definition: pub_message.h:45
SCIP_Bool SCIPboundchgIsRedundant(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16599
void SCIPlpDecNLoosevars(SCIP_LP *lp)
Definition: lp.c:13844
SCIP_Real SCIPvarGetLbOriginal(SCIP_VAR *var)
Definition: var.c:17222
void SCIPcliqueDelVar(SCIP_CLIQUE *clique, SCIP_CLIQUETABLE *cliquetable, SCIP_VAR *var, SCIP_Bool value)
Definition: implics.c:1263
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:237
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:16232
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:14333
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:911
SCIP_Longint lpcount
Definition: struct_stat.h:171
SCIP_Bool SCIPbdchgidxIsEarlierNonNull(SCIP_BDCHGIDX *bdchgidx1, SCIP_BDCHGIDX *bdchgidx2)
Definition: var.c:17818
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:628
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:5901
int SCIPvarCompareActiveAndNegated(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11315
int lbchginfossize
Definition: struct_var.h:260
SCIP_Real SCIPvarGetAvgBranchdepthCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15238
unsigned int varstatus
Definition: struct_var.h:274
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:17242
SCIP_Bool SCIPvarIsTransformedOrigvar(SCIP_VAR *var)
Definition: var.c:12271
SCIP_Real SCIPhistoryGetAvgBranchdepth(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:681
SCIP_Real bestrootlpobjval
Definition: struct_var.h:209
SCIP_VARDATA * vardata
Definition: struct_var.h:234
SCIPInterval sqrt(const SCIPInterval &x)
SCIP_RETCODE SCIPvarChgObjDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newobj)
Definition: var.c:6089
SCIP_EVENTTYPE eventmask
Definition: struct_event.h:180
SCIP_DECL_SORTPTRCOMP(SCIPvarCompActiveAndNegated)
Definition: var.c:11345
SCIP_Real SCIPvarGetPseudocostCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_Real solvaldelta)
Definition: var.c:13930
SCIP_Real SCIPvarGetUbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:16071
SCIP_Bool SCIPsortedvecFindPtr(void **ptrarray, SCIP_DECL_SORTPTRCOMP((*ptrcomp)), void *val, int len, int *pos)
SCIP_Real primsolavg
Definition: struct_var.h:212
void SCIPstrCopySection(const char *str, char startchar, char endchar, char *token, int size, char **endptr)
Definition: misc.c:10112
SCIP_Bool SCIPvarHasBinaryImplic(SCIP_VAR *var, SCIP_Bool varfixing, SCIP_VAR *implvar, SCIP_Bool implvarfixing)
Definition: var.c:10580
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:144
const char * SCIPconsGetName(SCIP_CONS *cons)
Definition: cons.c:7986
SCIP_Real * SCIPvarGetVubConstants(SCIP_VAR *var)
Definition: var.c:17542
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:6646
SCIP_OBJSENSE objsense
Definition: struct_prob.h:77
unsigned int pos
Definition: struct_var.h:113
static SCIP_RETCODE varSetName(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_STAT *stat, const char *name)
Definition: var.c:1823
SCIP_Real SCIPvarGetAggrConstant(SCIP_VAR *var)
Definition: var.c:17033
SCIP_Real SCIPcolGetLb(SCIP_COL *col)
Definition: lp.c:16175
struct SCIP_EventData SCIP_EVENTDATA
Definition: type_event.h:155
const char * SCIPvarGetName(SCIP_VAR *var)
Definition: var.c:16662
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:4808
SCIP_VAR * transvar
Definition: struct_var.h:170
SCIP_DOMCHGDYN domchgdyn
Definition: struct_var.h:155
#define MAXDNOM
SCIP_Real SCIPsetFeasCeil(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6352
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:1881
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:11396
unsigned int initial
Definition: struct_var.h:268
void SCIPvarGetClosestVub(SCIP_VAR *var, SCIP_SOL *sol, SCIP_SET *set, SCIP_STAT *stat, SCIP_Real *closestvub, int *closestvubidx)
Definition: var.c:13603
SCIP_NEGATE negate
Definition: struct_var.h:227
SCIP_RETCODE SCIPvarFlattenAggregationGraph(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: var.c:4237
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:7272
SCIP_RETCODE SCIPvarSetRelaxSol(SCIP_VAR *var, SCIP_SET *set, SCIP_RELAXATION *relaxation, SCIP_Real solval, SCIP_Bool updateobj)
Definition: var.c:13268
SCIP_HISTORY * glbhistory
Definition: struct_stat.h:162
SCIP_Real SCIPboundchgGetNewbound(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16559
SCIP_Real * SCIPvboundsGetCoefs(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3279
#define REALABS(x)
Definition: def.h:173
int nparentvars
Definition: struct_var.h:255
SCIP_Real SCIPvarGetLPSol(SCIP_VAR *var)
Definition: var.c:17650
SCIP_Real unchangedobj
Definition: struct_var.h:204
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:17296
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:9634
SCIP_Longint SCIPvarGetNActiveConflicts(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14674
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:17146
SCIP_Real SCIPvarCalcPscostConfidenceBound(SCIP_VAR *var, SCIP_SET *set, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun, SCIP_CONFIDENCELEVEL clevel)
Definition: var.c:14151
#define SCIP_CALL(x)
Definition: def.h:350
SCIP_Bool SCIPbdchginfoHasInferenceReason(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18017
SCIP_VBOUNDS * vubs
Definition: struct_var.h:238
SCIP_Real SCIPvarGetLbLazy(SCIP_VAR *var)
Definition: var.c:17414
SCIP_Bool SCIPsetIsFeasGE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6262
SCIP_Real * SCIPvarGetVlbConstants(SCIP_VAR *var)
Definition: var.c:17500
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:14853
SCIP_Real SCIPvarGetMultaggrConstant(SCIP_VAR *var)
Definition: var.c:17080
int SCIPprobGetNContVars(SCIP_PROB *prob)
Definition: prob.c:2341
SCIP_Real SCIPvarGetPseudocostCount(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:13977
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:9353
static SCIP_VAR * varGetActiveVar(SCIP_VAR *var)
Definition: var.c:5543
SCIP_Real * SCIPvboundsGetConstants(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3287
SCIP_Real SCIPvarGetCutoffSum(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15583
SCIP_Real * SCIPvarGetVubCoefs(SCIP_VAR *var)
Definition: var.c:17532
SCIP_Bool SCIPbdchginfoIsRedundant(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:18006
int closestvubidx
Definition: struct_var.h:267
internal methods for relaxators
SCIP_Real SCIPvarGetMinPseudocostScore(SCIP_VAR *var, SCIP_STAT *stat, SCIP_SET *set, SCIP_Real solval)
Definition: var.c:14065
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:5798
static SCIP_RETCODE varProcessChgBranchPriority(SCIP_VAR *var, int branchpriority)
Definition: var.c:11044
SCIP_Real vsidsweight
Definition: struct_stat.h:118
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:7731
#define SCIPdebugCheckLbGlobal(scip, var, lb)
Definition: debug.h:251
unsigned int nboundchgs
Definition: struct_var.h:141
SCIP_BDCHGIDX * SCIPbdchginfoGetIdx(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17928
SCIP_Longint SCIPvarGetNActiveConflictsCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:14721
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:276
int ubchginfossize
Definition: struct_var.h:262
SCIP_Bool SCIPcliquelistsHaveCommonClique(SCIP_CLIQUELIST *cliquelist1, SCIP_Bool value1, SCIP_CLIQUELIST *cliquelist2, SCIP_Bool value2)
Definition: implics.c:1583
SCIP_Bool SCIPsetIsFeasLE(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6218
#define SCIPdebugCheckUbGlobal(scip, var, ub)
Definition: debug.h:252
#define SCIP_EVENTTYPE_UBCHANGED
Definition: type_event.h:105
void SCIPvboundsShrink(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem, int newnvbds)
Definition: implics.c:328
void SCIPvarSetBestRootSol(SCIP_VAR *var, SCIP_Real rootsol, SCIP_Real rootredcost, SCIP_Real rootlpobjval)
Definition: var.c:13253
int var_probindex
Definition: struct_lp.h:169
void SCIPvarAdjustBd(SCIP_VAR *var, SCIP_SET *set, SCIP_BOUNDTYPE boundtype, SCIP_Real *bd)
Definition: var.c:6186
#define BMSfreeBlockMemory(mem, ptr)
Definition: memory.h:446
data structures and methods for collecting reoptimization information
internal methods for problem variables
SCIP_Bool SCIPvarIsOriginal(SCIP_VAR *var)
Definition: var.c:16791
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:5874
SCIP_RETCODE SCIPvarChgBranchFactor(SCIP_VAR *var, SCIP_SET *set, SCIP_Real branchfactor)
Definition: var.c:10974
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:5034
#define SCIP_UNKNOWN
Definition: def.h:170
SCIP_Bool SCIPsetIsIntegral(SCIP_SET *set, SCIP_Real val)
Definition: set.c:5921
unsigned int vartype
Definition: struct_var.h:273
SCIP_BOUNDTYPE * SCIPvarGetImplTypes(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17586
unsigned int boundchgtype
Definition: struct_var.h:91
#define BMSfreeBlockMemorySize(mem, ptr, size)
Definition: memory.h:450
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:15021
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:6321
SCIP_VAR * var
Definition: struct_var.h:90
SCIP_INFERENCEDATA inferencedata
Definition: struct_var.h:88
SCIP_Real SCIPholelistGetRight(SCIP_HOLELIST *holelist)
Definition: var.c:16639
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:8626
#define SCIP_Bool
Definition: def.h:61
void SCIPvarCapture(SCIP_VAR *var)
Definition: var.c:2753
#define BMSreallocBlockMemorySize(mem, ptr, oldsize, newsize)
Definition: memory.h:437
SCIP_BOUNDCHGTYPE SCIPboundchgGetBoundchgtype(SCIP_BOUNDCHG *boundchg)
Definition: var.c:16579
SCIP_Real ub
Definition: struct_var.h:162
unsigned int boundtype
Definition: struct_var.h:92
int SCIPbdchginfoGetPos(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17918
unsigned int deletable
Definition: struct_var.h:270
enum SCIP_Objsense SCIP_OBJSENSE
Definition: type_prob.h:41
SCIP_Bool SCIPvarWasFixedEarlier(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:16363
SCIP_Real SCIPvarGetInferenceSumCurrentRun(SCIP_VAR *var, SCIP_BRANCHDIR dir)
Definition: var.c:15428
SCIP_Bool SCIPvarIsInLP(SCIP_VAR *var)
Definition: var.c:17001
SCIP_RETCODE SCIPvarRemove(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_CLIQUETABLE *cliquetable, SCIP_SET *set, SCIP_Bool final)
Definition: var.c:5768
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:12677
SCIP_Real SCIPvarGetNLPSol(SCIP_VAR *var)
Definition: var.c:17663
int SCIPvarGetBranchPriority(SCIP_VAR *var)
Definition: var.c:17448
int SCIPgetDepth(SCIP *scip)
Definition: scip.c:43045
SCIP_Real SCIPvarGetLbAtIndex(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15947
SCIP_Bool divingobjchg
Definition: struct_lp.h:362
int SCIPvarGetNImpls(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17554
SCIP_MULTAGGR multaggr
Definition: struct_var.h:226
SCIP_RETCODE SCIPvarChgUbDive(SCIP_VAR *var, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newbound)
Definition: var.c:7972
#define BMSfreeBlockMemoryArray(mem, ptr, num)
Definition: memory.h:448
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:271
int * SCIPimplicsGetIds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3334
SCIP_VARDATA * SCIPvarGetData(SCIP_VAR *var)
Definition: var.c:16682
SCIP_RETCODE SCIPcolChgLb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newlb)
Definition: lp.c:3660
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:10082
int SCIPimplicsGetNImpls(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3295
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:16569
int SCIPvarCompare(SCIP_VAR *var1, SCIP_VAR *var2)
Definition: var.c:11353
methods for debugging
SCIP_Bool * SCIPcliqueGetValues(SCIP_CLIQUE *clique)
Definition: implics.c:3365
SCIP_BOUNDCHG * SCIPdomchgGetBoundchg(SCIP_DOMCHG *domchg, int pos)
Definition: var.c:16617
SCIP_Real SCIPvarGetUnchangedObj(SCIP_VAR *var)
Definition: var.c:17134
unsigned int removable
Definition: struct_var.h:269
#define SCIPsetDebugMsg
Definition: set.h:1913
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:8265
unsigned int redundant
Definition: struct_var.h:95
SCIP_Real oldbound
Definition: struct_var.h:108
SCIP_Real SCIPvarGetObj(SCIP_VAR *var)
Definition: var.c:17124
SCIP_RETCODE SCIPvarAddCliqueToList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10807
SCIP_Real SCIPbdchginfoGetNewbound(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17868
SCIP_Real SCIPvarGetBestRootRedcost(SCIP_VAR *var)
Definition: var.c:13188
SCIP_VAR * SCIPvarGetAggrVar(SCIP_VAR *var)
Definition: var.c:17011
int closestvlbidx
Definition: struct_var.h:266
#define EPSLE(x, y, eps)
Definition: def.h:176
int nuses
Definition: struct_var.h:256
SCIP_Real SCIPvarGetAvgInferencesCurrentRun(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15528
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:10593
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:10846
#define SCIP_EVENTTYPE_GHOLEADDED
Definition: type_event.h:67
#define BMScopyMemoryArray(ptr, source, num)
Definition: memory.h:116
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:16990
int probindex
Definition: struct_var.h:249
static SCIP_RETCODE varProcessAddHoleGlobal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_EVENTQUEUE *eventqueue, SCIP_Real left, SCIP_Real right, SCIP_Bool *added)
Definition: var.c:8378
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:2077
SCIP_Real SCIPvarGetRelaxSol(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:13329
int SCIPvarGetMultaggrNVars(SCIP_VAR *var)
Definition: var.c:17044
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:17600
SCIP_RETCODE SCIPvarGetOrigvarSum(SCIP_VAR **var, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12184
SCIP_Bool SCIPsetIsFeasLT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6196
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:2358
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:14593
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:9145
SCIP_NODE * SCIPgetFocusNode(SCIP *scip)
Definition: scip.c:41385
SCIP_RETCODE SCIPcolChgUb(SCIP_COL *col, SCIP_SET *set, SCIP_LP *lp, SCIP_Real newub)
Definition: lp.c:3705
SCIP_RETCODE SCIPcolFree(SCIP_COL **col, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_EVENTQUEUE *eventqueue, SCIP_LP *lp)
Definition: lp.c:3280
SCIP * scip
Definition: struct_var.h:201
SCIP_EVENTFILTER * eventfilter
Definition: struct_var.h:241
static SCIP_Real SCIPvarGetPseudoSol_rec(SCIP_VAR *var)
Definition: var.c:12599
int nlocksup
Definition: struct_var.h:258
SCIP_BDCHGINFO * SCIPvarGetLbchgInfo(SCIP_VAR *var, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15814
SCIP_Bool SCIPprobIsTransformed(SCIP_PROB *prob)
Definition: prob.c:2240
SCIP_BOUNDTYPE SCIPbdchginfoGetInferBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17985
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:15870
int conflictubcount
Definition: struct_var.h:265
int SCIPvboundsGetNVbds(SCIP_VBOUNDS *vbounds)
Definition: implics.c:3263
SCIP_RETCODE SCIPvarGetProbvarBound(SCIP_VAR **var, SCIP_Real *bound, SCIP_BOUNDTYPE *boundtype)
Definition: var.c:11879
static SCIP_RETCODE parseValue(SCIP_SET *set, const char *str, SCIP_Real *value, char **endptr)
Definition: var.c:2189
SCIP_DOM locdom
Definition: struct_var.h:220
SCIP_BDCHGINFO * SCIPvarGetBdchgInfoUb(SCIP_VAR *var, int pos)
Definition: var.c:17696
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:9426
SCIP_BDCHGINFO * SCIPvarGetBdchgInfo(SCIP_VAR *var, SCIP_BOUNDTYPE boundtype, SCIP_BDCHGIDX *bdchgidx, SCIP_Bool after)
Definition: var.c:15926
#define SCIP_REAL_MAX
Definition: def.h:150
SCIP_Bool SCIPsetIsDualfeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6506
SCIP_VALUEHISTORY * valuehistory
Definition: struct_var.h:246
static void printBounds(SCIP_SET *set, SCIP_MESSAGEHDLR *messagehdlr, FILE *file, SCIP_Real lb, SCIP_Real ub, const char *name)
Definition: var.c: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:13675
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:84
#define SCIP_REAL_MIN
Definition: def.h:151
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:235
SCIP_BRANCHDIR SCIPbranchdirOpposite(SCIP_BRANCHDIR dir)
Definition: history.c:414
SCIP_VAR ** SCIPvarGetImplVars(SCIP_VAR *var, SCIP_Bool varfixing)
Definition: var.c:17571
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:6341
SCIP_DOMCHGBOUND domchgbound
Definition: struct_var.h:153
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:7153
#define SCIP_DEFAULT_INFINITY
Definition: def.h:154
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:52
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:434
unsigned int boundtype
Definition: struct_var.h:115
#define SCIPsetFreeCleanBufferArray(set, ptr)
Definition: set.h:1891
void SCIPrelaxationSolObjAdd(SCIP_RELAXATION *relaxation, SCIP_Real val)
Definition: relax.c:690
static const SCIP_Real scalars[]
Definition: lp.c:5618
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:5200
int lpipos
Definition: struct_lp.h:164
SCIP_NODE * SCIPtreeGetRootNode(SCIP_TREE *tree)
Definition: tree.c:8352
int SCIPdomchgGetNBoundchgs(SCIP_DOMCHG *domchg)
Definition: var.c:16609
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:2021
SCIP_Real lazyub
Definition: struct_var.h:218
int SCIPbdchginfoGetDepth(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17908
SCIP_RETCODE SCIPeventfilterFree(SCIP_EVENTFILTER **eventfilter, BMS_BLKMEM *blkmem, SCIP_SET *set)
Definition: event.c:1723
#define SCIP_EVENTTYPE_FORMAT
Definition: type_event.h:135
unsigned int redundant
Definition: struct_var.h:117
SCIP_MESSAGEHDLR * messagehdlr
Definition: struct_visual.h:44
SCIP_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:14266
SCIP_DECL_HASHKEYEQ(SCIPvarIsHashkeyEq)
Definition: var.c:11402
SCIP_Real SCIPvarGetBestRootSol(SCIP_VAR *var)
Definition: var.c:13122
SCIP_VAR * var
Definition: struct_var.h:110
public methods for message output
int nrootboundchgsrun
Definition: struct_stat.h:203
void SCIPcliquelistCheck(SCIP_CLIQUELIST *cliquelist, SCIP_VAR *var)
Definition: implics.c:3437
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:16738
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:8917
SCIP_Real * scalars
Definition: struct_var.h:185
SCIP_IMPLICS * implics
Definition: struct_var.h:239
SCIP_Real SCIPholelistGetLeft(SCIP_HOLELIST *holelist)
Definition: var.c:16629
SCIP_Bool SCIPsetIsGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:5852
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:16781
SCIP_RETCODE SCIPvarResetBounds(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:8864
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:9046
#define SCIP_Real
Definition: def.h:149
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:15105
SCIP_RETCODE SCIPvarsGetProbvarBinary(SCIP_VAR ***vars, SCIP_Bool **negatedarr, int nvars)
Definition: var.c:11688
SCIP_VAR * SCIPbdchginfoGetInferVar(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17938
SCIP_Bool SCIPsetIsFeasPositive(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6295
int parentvarssize
Definition: struct_var.h:254
SCIP_CLIQUELIST * cliquelist
Definition: struct_var.h:240
SCIP_RETCODE SCIPvarSetInitial(SCIP_VAR *var, SCIP_Bool initial)
Definition: var.c:16749
SCIP_VAR ** SCIPprobGetVars(SCIP_PROB *prob)
Definition: prob.c:2350
SCIP_RETCODE SCIPvarGetProbvarHole(SCIP_VAR **var, SCIP_Real *left, SCIP_Real *right)
Definition: var.c:11972
SCIP_RETCODE SCIPlpUpdateVarLoose(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13823
SCIP_Real SCIPvarGetVSIDS(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:17741
#define SCIP_INVALID
Definition: def.h:169
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:16672
void SCIPvarsGetProbvar(SCIP_VAR **vars, int nvars)
Definition: var.c:11608
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:2218
SCIP_VAR ** SCIPvarGetVubVars(SCIP_VAR *var)
Definition: var.c:17522
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:443
SCIP_Real branchfactor
Definition: struct_var.h:205
unsigned int donotmultaggr
Definition: struct_var.h:272
#define SCIP_Longint
Definition: def.h:134
SCIP_BOUNDTYPE SCIPvarGetBestBoundType(SCIP_VAR *var)
Definition: var.c:17388
SCIP_CONS * SCIPbdchginfoGetInferCons(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17950
SCIP_Bool SCIPsetIsDualfeasZero(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6495
SCIP_Real SCIPvarGetAvgSol(SCIP_VAR *var)
Definition: var.c:13468
int SCIPvarGetIndex(SCIP_VAR *var)
Definition: var.c:16959
SCIP_Real nlpsol
Definition: struct_var.h:211
SCIP_VAR * lastbranchvar
Definition: struct_stat.h:164
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:15669
SCIP_Real lb
Definition: struct_var.h:161
SCIP_VAR * var
Definition: struct_lp.h:151
SCIP_Bool SCIPsetIsFeasGT(SCIP_SET *set, SCIP_Real val1, SCIP_Real val2)
Definition: set.c:6240
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:8755
SCIP_VARTYPE SCIPvarGetType(SCIP_VAR *var)
Definition: var.c:16827
SCIP_Real SCIPvarGetMultaggrUbLocal(SCIP_VAR *var, SCIP_SET *set)
Definition: var.c:8133
SCIP_RETCODE SCIPvarChgName(SCIP_VAR *var, BMS_BLKMEM *blkmem, const char *name)
Definition: var.c:2792
SCIP_DOM glbdom
Definition: struct_var.h:219
SCIP_Real SCIPsetEpsilon(SCIP_SET *set)
Definition: set.c:5658
SCIP_Real SCIPhistoryGetAvgInferences(SCIP_HISTORY *history, SCIP_BRANCHDIR dir)
Definition: history.c:642
SCIP_STAGE SCIPsetGetStage(SCIP_SET *set)
Definition: set.c:2781
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:6359
SCIP_Bool collectvarhistory
Definition: struct_stat.h:261
SCIP_VAR * negatedvar
Definition: struct_var.h:236
SCIP_Bool SCIPvarIsMarkedDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16929
SCIP_Bool SCIPcliqueIsCleanedUp(SCIP_CLIQUE *clique)
Definition: implics.c:3399
SCIP_Real newbound
Definition: struct_var.h:109
SCIP_Real SCIPvarGetUbLocal(SCIP_VAR *var)
Definition: var.c:17342
int nlocksdown
Definition: struct_var.h:257
int SCIPcliqueGetNVars(SCIP_CLIQUE *clique)
Definition: implics.c:3343
SCIP_RETCODE SCIPvarAddHoleOriginal(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_Real left, SCIP_Real right)
Definition: var.c:8326
void SCIPbdchginfoFree(SCIP_BDCHGINFO **bdchginfo, BMS_BLKMEM *blkmem)
Definition: var.c:15800
void SCIPvarAdjustUb(SCIP_VAR *var, SCIP_SET *set, SCIP_Real *ub)
Definition: var.c:6169
SCIP_Bool SCIPvarIsTransformed(SCIP_VAR *var)
Definition: var.c:16804
static void varIncRootboundchgs(SCIP_VAR *var, SCIP_SET *set, SCIP_STAT *stat)
Definition: var.c:6429
#define BMSallocBlockMemory(mem, ptr)
Definition: memory.h:433
SCIP_HOLELIST * SCIPvarGetHolelistLocal(SCIP_VAR *var)
Definition: var.c:17352
unsigned int delglobalstructs
Definition: struct_var.h:278
SCIP_Bool SCIPsetIsDualfeasNegative(SCIP_SET *set, SCIP_Real val)
Definition: set.c:6517
SCIP_BOUNDTYPE SCIPbdchginfoGetBoundtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17898
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:17783
SCIP_Real rootsol
Definition: struct_var.h:206
SCIP_Bool SCIPeventqueueIsDelayed(SCIP_EVENTQUEUE *eventqueue)
Definition: event.c:2440
SCIP_RETCODE SCIPhashmapInsert(SCIP_HASHMAP *hashmap, void *origin, void *image)
Definition: misc.c:2874
SCIP_RETCODE SCIPlpUpdateVarColumn(SCIP_LP *lp, SCIP_SET *set, SCIP_VAR *var)
Definition: lp.c:13699
SCIP_HISTORY * history
Definition: struct_var.h:244
common defines and data types used in all packages of SCIP
SCIP_RETCODE SCIPvarSetRemovable(SCIP_VAR *var, SCIP_Bool removable)
Definition: var.c:16765
SCIP_Real SCIPvarGetVSIDS_rec(SCIP_VAR *var, SCIP_STAT *stat, SCIP_BRANCHDIR dir)
Definition: var.c:15283
int nrootintfixingsrun
Definition: struct_stat.h:205
struct BMS_BlkMem BMS_BLKMEM
Definition: memory.h:419
SCIP_RETCODE SCIPvarGetProbvarSum(SCIP_VAR **var, SCIP_SET *set, SCIP_Real *scalar, SCIP_Real *constant)
Definition: var.c:12057
#define SCIP_EVENTTYPE_GUBCHANGED
Definition: type_event.h:62
#define SCIP_CALL_ABORT(x)
Definition: def.h:329
SCIP_Real SCIPvarGetPseudoSol(SCIP_VAR *var)
Definition: var.c:17728
enum SCIP_BoundchgType SCIP_BOUNDCHGTYPE
Definition: type_var.h:78
SCIP_Real * SCIPimplicsGetBounds(SCIP_IMPLICS *implics, SCIP_Bool varfixing)
Definition: implics.c:3322
SCIP_ORIGINAL original
Definition: struct_var.h:223
SCIP_Real SCIPcolGetRedcost(SCIP_COL *col, SCIP_STAT *stat, SCIP_LP *lp)
Definition: lp.c:3855
SCIP_VAR * SCIPvarGetTransVar(SCIP_VAR *var)
Definition: var.c:16979
#define SCIP_ALLOC(x)
Definition: def.h:361
#define SCIPABORT()
Definition: def.h:322
SCIP_Bool SCIPvarIsIntegral(SCIP_VAR *var)
Definition: var.c:16853
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:8067
SCIP_Longint SCIPcalcGreComDiv(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8448
unsigned int applied
Definition: struct_var.h:94
SCIP_Bool SCIPvarIsDeleted(SCIP_VAR *var)
Definition: var.c:16883
void SCIPvboundsFree(SCIP_VBOUNDS **vbounds, BMS_BLKMEM *blkmem)
Definition: implics.c:68
SCIP_RETCODE SCIPvarsAddClique(SCIP_VAR **vars, SCIP_Bool *values, int nvars, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_CLIQUE *clique)
Definition: var.c:10769
SCIP_HOLELIST ** ptr
Definition: struct_var.h:58
#define BMSreallocBlockMemoryArray(mem, ptr, oldnum, newnum)
Definition: memory.h:439
SCIP_BOUNDCHG * boundchgs
Definition: struct_var.h:143
void SCIPvarMarkDeleted(SCIP_VAR *var)
Definition: var.c:5804
void SCIPvarSetData(SCIP_VAR *var, SCIP_VARDATA *vardata)
Definition: var.c:16692
SCIP_Bool SCIPcolIsInLP(SCIP_COL *col)
Definition: lp.c:16317
SCIP_COL * col
Definition: struct_var.h:224
SCIP_RETCODE SCIPvarNegate(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_STAT *stat, SCIP_VAR **negvar)
Definition: var.c:5627
SCIP_Real left
Definition: struct_var.h:44
SCIP_Longint SCIPcalcSmaComMul(SCIP_Longint val1, SCIP_Longint val2)
Definition: misc.c:8700
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:179
void SCIPimplicsFree(SCIP_IMPLICS **implics, BMS_BLKMEM *blkmem)
Definition: implics.c:446
static SCIP_RETCODE varProcessChgBranchDirection(SCIP_VAR *var, SCIP_BRANCHDIR branchdirection)
Definition: var.c:11163
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:6306
SCIP_Real SCIPvarGetPseudocostVariance(SCIP_VAR *var, SCIP_BRANCHDIR dir, SCIP_Bool onlycurrentrun)
Definition: var.c:14097
SCIP_Bool SCIPvarIsActive(SCIP_VAR *var)
Definition: var.c:16949
SCIP_Real objscale
Definition: struct_prob.h:42
SCIP_BDCHGINFO * lbchginfos
Definition: struct_var.h:242
static SCIP_RETCODE findValuehistoryEntry(SCIP_VAR *var, SCIP_Real value, BMS_BLKMEM *blkmem, SCIP_SET *set, SCIP_HISTORY **history)
Definition: var.c:14402
SCIP_RETCODE SCIPcliquelistDel(SCIP_CLIQUELIST **cliquelist, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: implics.c:1505
SCIP_Bool SCIPvarIsNegated(SCIP_VAR *var)
Definition: var.c:16817
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:5515
SCIP_Real scalar
Definition: struct_var.h:176
uint64_t SCIP_EVENTTYPE
Definition: type_event.h:134
void SCIPvarMarkDeleteGlobalStructures(SCIP_VAR *var)
Definition: var.c:16919
SCIP_BOUNDCHGTYPE SCIPbdchginfoGetChgtype(SCIP_BDCHGINFO *bdchginfo)
Definition: var.c:17888
SCIP_RETCODE SCIPvarDelCliqueFromList(SCIP_VAR *var, BMS_BLKMEM *blkmem, SCIP_Bool value, SCIP_CLIQUE *clique)
Definition: var.c:10829